From 8e7f9c9cbd5d23806e53f82a8bd345c0c7520f8b Mon Sep 17 00:00:00 2001 From: Eric Miotto <1094986+edymtt@users.noreply.github.com> Date: Tue, 26 Jan 2021 10:02:24 -0800 Subject: [PATCH] Revert "SIL: let SingleValueInstruction only inherit from a single SILNode." --- include/swift/SIL/ApplySite.h | 45 +- include/swift/SIL/DynamicCasts.h | 9 +- include/swift/SIL/PrettyStackTrace.h | 4 +- include/swift/SIL/SILArgument.h | 8 +- include/swift/SIL/SILInstruction.h | 531 ++++++++---------- include/swift/SIL/SILNode.h | 205 ++++--- include/swift/SIL/SILNodes.def | 1 - include/swift/SIL/SILPrintContext.h | 2 +- include/swift/SIL/SILUndef.h | 2 +- include/swift/SIL/SILValue.h | 14 +- .../SILOptimizer/Analysis/AliasAnalysis.h | 2 +- .../swift/SILOptimizer/Utils/InstOptUtils.h | 2 + .../SILOptimizer/Utils/LoadStoreOptUtils.h | 2 +- include/swift/SILOptimizer/Utils/SCCVisitor.h | 10 +- lib/SIL/IR/SILArgument.cpp | 2 +- lib/SIL/IR/SILBasicBlock.cpp | 2 +- lib/SIL/IR/SILFunction.cpp | 4 +- lib/SIL/IR/SILInstruction.cpp | 9 +- lib/SIL/IR/SILInstructions.cpp | 46 +- lib/SIL/IR/SILPrinter.cpp | 35 +- lib/SIL/IR/SILUndef.cpp | 2 +- lib/SIL/IR/SILValue.cpp | 42 +- lib/SIL/Utils/OwnershipUtils.cpp | 96 ++-- lib/SILOptimizer/ARC/ARCRegionState.cpp | 4 +- .../ARC/GlobalARCSequenceDataflow.cpp | 4 +- lib/SILOptimizer/ARC/RCStateTransition.cpp | 4 +- lib/SILOptimizer/ARC/RCStateTransition.h | 4 +- lib/SILOptimizer/ARC/RefCountState.cpp | 4 +- lib/SILOptimizer/Analysis/AliasAnalysis.cpp | 2 + lib/SILOptimizer/Analysis/EscapeAnalysis.cpp | 46 +- lib/SILOptimizer/Analysis/IVAnalysis.cpp | 3 +- .../Mandatory/DiagnoseInfiniteRecursion.cpp | 16 +- .../Mandatory/Differentiation.cpp | 5 +- lib/SILOptimizer/PassManager/PassManager.cpp | 2 +- .../Transforms/DeadCodeElimination.cpp | 59 +- lib/SILOptimizer/Transforms/SILMem2Reg.cpp | 2 +- lib/SILOptimizer/Utils/ConstExpr.cpp | 65 ++- lib/SILOptimizer/Utils/InstOptUtils.cpp | 14 + lib/SILOptimizer/Utils/LoadStoreOptUtils.cpp | 2 +- 39 files changed, 679 insertions(+), 632 deletions(-) diff --git a/include/swift/SIL/ApplySite.h b/include/swift/SIL/ApplySite.h index 48d80aa00cffd..d9e1cee676464 100644 --- a/include/swift/SIL/ApplySite.h +++ b/include/swift/SIL/ApplySite.h @@ -90,30 +90,28 @@ class ApplySite { SILModule &getModule() const { return Inst->getModule(); } - static ApplySite isa(SILInstruction *inst) { - auto kind = ApplySiteKind::fromNodeKind(inst->getKind()); + static ApplySite isa(SILNode *node) { + auto *i = dyn_cast(node); + if (!i) + return ApplySite(); + + auto kind = ApplySiteKind::fromNodeKind(i->getKind()); if (!kind) return ApplySite(); switch (kind.getValue()) { case ApplySiteKind::ApplyInst: - return ApplySite(cast(inst)); + return ApplySite(cast(node)); case ApplySiteKind::BeginApplyInst: - return ApplySite(cast(inst)); + return ApplySite(cast(node)); case ApplySiteKind::TryApplyInst: - return ApplySite(cast(inst)); + return ApplySite(cast(node)); case ApplySiteKind::PartialApplyInst: - return ApplySite(cast(inst)); + return ApplySite(cast(node)); } llvm_unreachable("covered switch"); } - static ApplySite isa(SILValue value) { - if (auto *inst = value->getDefiningInstruction()) - return ApplySite::isa(inst); - return ApplySite(); - } - ApplySiteKind getKind() const { return ApplySiteKind(Inst->getKind()); } explicit operator bool() const { return Inst != nullptr; } @@ -183,8 +181,8 @@ class ApplySite { /// Calls to (previous_)dynamic_function_ref have a dynamic target function so /// we should not optimize them. bool canOptimize() const { - return !swift::isa(getCallee()) && - !swift::isa(getCallee()); + return !DynamicFunctionRefInst::classof(getCallee()) && + !PreviousDynamicFunctionRefInst::classof(getCallee()); } /// Return the type. @@ -495,27 +493,24 @@ class FullApplySite : public ApplySite { FullApplySite(BeginApplyInst *inst) : ApplySite(inst) {} FullApplySite(TryApplyInst *inst) : ApplySite(inst) {} - static FullApplySite isa(SILInstruction *inst) { - auto kind = FullApplySiteKind::fromNodeKind(inst->getKind()); + static FullApplySite isa(SILNode *node) { + auto *i = dyn_cast(node); + if (!i) + return FullApplySite(); + auto kind = FullApplySiteKind::fromNodeKind(i->getKind()); if (!kind) return FullApplySite(); switch (kind.getValue()) { case FullApplySiteKind::ApplyInst: - return FullApplySite(cast(inst)); + return FullApplySite(cast(node)); case FullApplySiteKind::BeginApplyInst: - return FullApplySite(cast(inst)); + return FullApplySite(cast(node)); case FullApplySiteKind::TryApplyInst: - return FullApplySite(cast(inst)); + return FullApplySite(cast(node)); } llvm_unreachable("covered switch"); } - static FullApplySite isa(SILValue value) { - if (auto *inst = value->getDefiningInstruction()) - return FullApplySite::isa(inst); - return FullApplySite(); - } - FullApplySiteKind getKind() const { return FullApplySiteKind(getInstruction()->getKind()); } diff --git a/include/swift/SIL/DynamicCasts.h b/include/swift/SIL/DynamicCasts.h index 0d4e6bf642dc8..2f08945b77bc9 100644 --- a/include/swift/SIL/DynamicCasts.h +++ b/include/swift/SIL/DynamicCasts.h @@ -158,14 +158,17 @@ struct SILDynamicCastInst { SILDynamicCastInst(ID *i) : inst(i) {} #include "swift/SIL/SILNodes.def" - static SILDynamicCastInst getAs(SILInstruction *inst) { - auto kind = SILDynamicCastKind::fromNodeKind(inst->getKind()); + static SILDynamicCastInst getAs(SILNode *node) { + auto *i = dyn_cast(node); + if (!i) + return SILDynamicCastInst(); + auto kind = SILDynamicCastKind::fromNodeKind(i->getKind()); if (!kind) return SILDynamicCastInst(); switch (kind.getValue()) { #define DYNAMICCAST_INST(ID, PARENT) \ case SILDynamicCastKind::ID: \ - return SILDynamicCastInst(cast(inst)); + return SILDynamicCastInst(cast(node)); #include "swift/SIL/SILNodes.def" } } diff --git a/include/swift/SIL/PrettyStackTrace.h b/include/swift/SIL/PrettyStackTrace.h index acfff4e3ef2af..1b35d3ebf3c7f 100644 --- a/include/swift/SIL/PrettyStackTrace.h +++ b/include/swift/SIL/PrettyStackTrace.h @@ -19,12 +19,12 @@ #define SWIFT_SIL_PRETTYSTACKTRACE_H #include "swift/SIL/SILLocation.h" -#include "swift/SIL/SILNode.h" #include "llvm/Support/PrettyStackTrace.h" namespace swift { class ASTContext; class SILFunction; +class SILNode; void printSILLocationDescription(llvm::raw_ostream &out, SILLocation loc, ASTContext &ctx); @@ -74,7 +74,7 @@ class PrettyStackTraceSILNode : public llvm::PrettyStackTraceEntry { const char *Action; public: - PrettyStackTraceSILNode(const char *action, SILNodePointer node) + PrettyStackTraceSILNode(const char *action, const SILNode *node) : Node(node), Action(action) {} virtual void print(llvm::raw_ostream &OS) const override; diff --git a/include/swift/SIL/SILArgument.h b/include/swift/SIL/SILArgument.h index debe9aee198b9..e21f7e6eb9f26 100644 --- a/include/swift/SIL/SILArgument.h +++ b/include/swift/SIL/SILArgument.h @@ -78,7 +78,7 @@ class SILArgument : public ValueBase { explicit SILArgument(ValueKind subClassKind, SILType type, ValueOwnershipKind ownershipKind, const ValueDecl *inputDecl = nullptr) - : ValueBase(subClassKind, type), + : ValueBase(subClassKind, type, IsRepresentative::Yes), parentBlock(nullptr), decl(inputDecl) { Bits.SILArgument.VOKind = static_cast(ownershipKind); } @@ -106,7 +106,7 @@ class SILArgument : public ValueBase { static bool classof(const SILInstruction *) = delete; static bool classof(const SILUndef *) = delete; - static bool classof(SILNodePointer node) { + static bool classof(const SILNode *node) { return node->getKind() >= SILNodeKind::First_SILArgument && node->getKind() <= SILNodeKind::Last_SILArgument; } @@ -279,7 +279,7 @@ class SILPhiArgument : public SILArgument { static bool classof(const SILInstruction *) = delete; static bool classof(const SILUndef *) = delete; - static bool classof(SILNodePointer node) { + static bool classof(const SILNode *node) { return node->getKind() == SILNodeKind::SILPhiArgument; } }; @@ -322,7 +322,7 @@ class SILFunctionArgument : public SILArgument { static bool classof(const SILInstruction *) = delete; static bool classof(const SILUndef *) = delete; - static bool classof(SILNodePointer node) { + static bool classof(const SILNode *node) { return node->getKind() == SILNodeKind::SILFunctionArgument; } }; diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h index 88e297836be94..0191ee733dd1e 100644 --- a/include/swift/SIL/SILInstruction.h +++ b/include/swift/SIL/SILInstruction.h @@ -306,17 +306,8 @@ SILInstructionResultArray::getReversedValues() const { /// not captured by the formal operands; currently, these dependencies /// only arise due to certain instructions (e.g. open_existential_addr) /// that bind new archetypes in the local context. -/// -/// Conceptually, SILInstruction is a sub-class of SILNode. But implementation- -/// wise, only the two sub-classes of SILInstruction - SingleValueInstruction -/// and NonSingleValueInstruction - inherit from SILNode. Although the -/// SingleValueInstruction's SILNode is embedded into a ValueBase, its relative -/// offset in the class is the same as in NonSingleValueInstruction (see -/// SILNodeOffsetChecker). This makes it possible to cast from a SILInstruction -/// to a SILNode without knowing which SILInstruction sub-class it is. -/// Note that casting a SILInstruction to a SILNode cannot be done implicitly, -/// but only with an LLVM `cast` or with SILInstruction::asSILNode(). -class SILInstruction : public llvm::ilist_node { +class SILInstruction + : public SILNode, public llvm::ilist_node { friend llvm::ilist_traits; friend llvm::ilist_traits; friend SILBasicBlock; @@ -360,7 +351,9 @@ class SILInstruction : public llvm::ilist_node { SILInstructionResultArray getResultsImpl() const; protected: - SILInstruction(SILDebugLocation DebugLoc) : + SILInstruction(SILInstructionKind kind, SILDebugLocation DebugLoc) + : SILNode(SILNodeKind(kind), SILNodeStorageLocation::Instruction, + IsRepresentative::Yes), ParentBB(nullptr), Location(DebugLoc) { NumCreatedInstructions++; } @@ -406,16 +399,17 @@ class SILInstruction : public llvm::ilist_node { DoesNotRelease, MayRelease, }; - - SILNode *asSILNode(); - const SILNode *asSILNode() const; LLVM_ATTRIBUTE_ALWAYS_INLINE - SILInstructionKind getKind() const; + SILInstructionKind getKind() const { + return SILInstructionKind(SILNode::getKind()); + } - SILBasicBlock *getParent() const { return ParentBB; } + const SILBasicBlock *getParent() const { return ParentBB; } + SILBasicBlock *getParent() { return ParentBB; } - SILFunction *getFunction() const; + SILFunction *getFunction(); + const SILFunction *getFunction() const; /// Is this instruction part of a static initializer of a SILGlobalVariable? bool isStaticInitializerInst() const { return getFunction() == nullptr; } @@ -739,9 +733,9 @@ class SILInstruction : public llvm::ilist_node { void dumpInContext() const; void printInContext(raw_ostream &OS) const; - static bool classof(SILNodePointer node) { - return node->getKind() >= SILNodeKind::First_SILInstruction && - node->getKind() <= SILNodeKind::Last_SILInstruction; + static bool classof(const SILNode *N) { + return N->getKind() >= SILNodeKind::First_SILInstruction && + N->getKind() <= SILNodeKind::Last_SILInstruction; } static bool classof(const SILInstruction *I) { return true; } @@ -749,79 +743,6 @@ class SILInstruction : public llvm::ilist_node { static bool classof(const ValueBase *) = delete; }; -inline SILNodePointer::SILNodePointer(const SILInstruction *inst) : - node(inst->asSILNode()) { } - -/// The base class for all instructions, which are not SingleValueInstructions: -/// NonValueInstruction and MultipleValueInstruction. -class NonSingleValueInstruction : public SILInstruction, public SILNode { - friend struct SILNodeOffsetChecker; -public: - NonSingleValueInstruction(SILInstructionKind kind, SILDebugLocation loc) - : SILInstruction(loc), SILNode((SILNodeKind)kind) {} - - using SILInstruction::operator new; - using SILInstruction::dumpInContext; - using SILInstruction::print; - using SILInstruction::printInContext; - - // Redeclare because lldb currently doesn't know about using-declarations - void dump() const; - SILFunction *getFunction() const { return SILInstruction::getFunction(); } - SILModule &getModule() const { return SILInstruction::getModule(); } - - /// Doesn't produce any results. - SILType getType() const = delete; - - LLVM_ATTRIBUTE_ALWAYS_INLINE - SILInstructionKind getKind() const { - return (SILInstructionKind)SILNode::getKind(); - } - - static bool classof(const ValueBase *value) = delete; - static bool classof(SILNodePointer node) { - return node->getKind() >= SILNodeKind::First_NonSingleValueInstruction && - node->getKind() <= SILNodeKind::Last_NonSingleValueInstruction; - } - static bool classof(const NonSingleValueInstruction *) { return true; } -}; - -inline SILNode *SILInstruction::asSILNode() { - // Even if this insttruction is not a NonSingleValueInstruction, but a - // SingleValueInstruction, the SILNode is at the same offset as in a - // NonSingleValueInstruction. See the top-level comment of SILInstruction. - SILNode *node = (NonSingleValueInstruction *)this; - assert(isa(node) || - isa(node)); - return node; -} -inline const SILNode *SILInstruction::asSILNode() const { - return (const_cast(this))->asSILNode(); -} - -inline SILNodePointer::SILNodePointer(const NonSingleValueInstruction *nsvi) : - node(nsvi) { } - -inline SILInstructionKind SILInstruction::getKind() const { - return SILInstructionKind(asSILNode()->getKind()); -} - -inline SILInstruction *SILNode::castToInstruction() { - assert(isa(this)); - // We use the same trick here as in SILInstruction::asSILNode(). - auto *nsvi = (NonSingleValueInstruction *)this; - assert((SILNodeKind)nsvi->getKind() == getKind()); - return nsvi; -} - -inline SILNode *SILNode::instAsNode(SILInstruction *inst) { - return inst->asSILNode(); -} -inline const SILNode *SILNode::instAsNode(const SILInstruction *inst) { - return inst->asSILNode(); -} - - struct SILInstruction::OperandToValue { const SILInstruction &i; bool skipTypeDependentOps; @@ -920,17 +841,20 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, /// both of which inherit from SILNode, it introduces the need for /// some care when working with SILNodes. See the comment on SILNode. class SingleValueInstruction : public SILInstruction, public ValueBase { - friend class SILInstruction; - friend struct SILNodeOffsetChecker; + static bool isSingleValueInstKind(SILNodeKind kind) { + return kind >= SILNodeKind::First_SingleValueInstruction && + kind <= SILNodeKind::Last_SingleValueInstruction; + } + friend class SILInstruction; SILInstructionResultArray getResultsImpl() const { return SILInstructionResultArray(this); } public: SingleValueInstruction(SILInstructionKind kind, SILDebugLocation loc, SILType type) - : SILInstruction(loc), - ValueBase(ValueKind(kind), type) {} + : SILInstruction(kind, loc), + ValueBase(ValueKind(kind), type, IsRepresentative::No) {} using SILInstruction::operator new; using SILInstruction::dumpInContext; @@ -939,11 +863,12 @@ class SingleValueInstruction : public SILInstruction, public ValueBase { // Redeclare because lldb currently doesn't know about using-declarations void dump() const; - SILFunction *getFunction() const { return SILInstruction::getFunction(); } - SILModule &getModule() const { return SILInstruction::getModule(); } - SILInstructionKind getKind() const { - return (SILInstructionKind)ValueBase::getKind(); + SILFunction *getFunction() { return SILInstruction::getFunction(); } + const SILFunction *getFunction() const { + return SILInstruction::getFunction(); } + SILModule &getModule() const { return SILInstruction::getModule(); } + SILInstructionKind getKind() const { return SILInstruction::getKind(); } void operator delete(void *Ptr, size_t) = delete; @@ -958,37 +883,44 @@ class SingleValueInstruction : public SILInstruction, public ValueBase { /// Override this to reflect the more efficient access pattern. SILInstructionResultArray getResults() const { return getResultsImpl(); } - static bool classof(SILNodePointer node) { - return node->getKind() >= SILNodeKind::First_SingleValueInstruction && - node->getKind() <= SILNodeKind::Last_SingleValueInstruction; + static bool classof(const SILNode *node) { + return isSingleValueInstKind(node->getKind()); } }; -struct SILNodeOffsetChecker { - static_assert(offsetof(SingleValueInstruction, Bits) == - offsetof(NonSingleValueInstruction, Bits), - "wrong SILNode layout in SILInstruction"); -}; - -inline SILNodePointer::SILNodePointer(const SingleValueInstruction *svi) : - node(svi) { } - -// Resolve SILInstruction vs SILNode ambiguities. -inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const NonSingleValueInstruction &I) { - cast(&I)->print(OS); - return OS; -} +// Resolve ambiguities. inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SingleValueInstruction &I) { - cast(&I)->print(OS); + I.print(OS); return OS; } +inline SingleValueInstruction *SILNode::castToSingleValueInstruction() { + assert(isa(this)); + + // We do reference static_casts to convince the host compiler to do + // null-unchecked conversions. + + // If we're in the value slot, cast through ValueBase. + if (getStorageLoc() == SILNodeStorageLocation::Value) { + return &static_cast( + static_cast(*this)); + + // Otherwise, cast through SILInstruction. + } else { + return &static_cast( + static_cast(*this)); + } +} + #define DEFINE_ABSTRACT_SINGLE_VALUE_INST_BOILERPLATE(ID) \ - static bool classof(SILNodePointer node) { \ + static bool classof(const SILNode *node) { \ return node->getKind() >= SILNodeKind::First_##ID && \ node->getKind() <= SILNodeKind::Last_##ID; \ + } \ + static bool classof(const SingleValueInstruction *inst) { \ + return inst->getKind() >= SILInstructionKind::First_##ID && \ + inst->getKind() <= SILInstructionKind::Last_##ID; \ } /// Abstract base class used for isa checks on instructions to determine if they @@ -1017,8 +949,9 @@ class OwnershipForwardingMixin { /// Defined inline below due to forward declaration issues. static bool isa(SILInstructionKind kind); static bool isa(const SILInstruction *inst) { return isa(inst->getKind()); } - static bool isa(SILNodePointer node) { - if (auto *i = dyn_cast(node.get())) + static bool isa(const SILNode *node) { + node = node->getRepresentativeSILNodeInObject(); + if (auto *i = dyn_cast(node)) return isa(i); return false; } @@ -1043,8 +976,8 @@ class FirstArgOwnershipForwardingSingleValueInst } public: - static bool classof(SILNodePointer node) { - if (auto *i = dyn_cast(node.get())) + static bool classof(const SILNode *node) { + if (auto *i = dyn_cast(node)) return classof(i); return false; } @@ -1076,8 +1009,8 @@ class OwnedFirstArgForwardingSingleValueInst return OwnershipKind::Owned; } - static bool classof(SILNodePointer node) { - if (auto *i = dyn_cast(node.get())) + static bool classof(const SILNode *node) { + if (auto *i = dyn_cast(node)) return classof(i); return false; } @@ -1115,8 +1048,8 @@ class GuaranteedFirstArgForwardingSingleValueInst return OwnershipKind::Guaranteed; } - static bool classof(SILNodePointer node) { - if (auto *i = dyn_cast(node.get())) + static bool classof(const SILNode *node) { + if (auto *i = dyn_cast(node)) return classof(i); return false; } @@ -1175,8 +1108,8 @@ class AllArgOwnershipForwardingSingleValueInst } public: - static bool classof(SILNodePointer node) { - if (auto *i = dyn_cast(node.get())) + static bool classof(const SILNode *node) { + if (auto *i = dyn_cast(node)) return classof(i); return false; } @@ -1242,7 +1175,7 @@ class MultipleValueInstructionResult : public ValueBase { static bool classof(const SILUndef *) = delete; static bool classof(const SILArgument *) = delete; static bool classof(const MultipleValueInstructionResult *) { return true; } - static bool classof(SILNodePointer node) { + static bool classof(const SILNode *node) { // This is an abstract class without anything implementing it right now, so // just return false. This will be fixed in a subsequent commit. SILNodeKind kind = node->getKind(); @@ -1265,13 +1198,13 @@ SILInstructionResultArray::SILInstructionResultArray(ArrayRef results) } /// An instruction that may produce an arbitrary number of values. -class MultipleValueInstruction : public NonSingleValueInstruction { +class MultipleValueInstruction : public SILInstruction { friend class SILInstruction; friend class SILInstructionResultArray; protected: MultipleValueInstruction(SILInstructionKind kind, SILDebugLocation loc) - : NonSingleValueInstruction(kind, loc) {} + : SILInstruction(kind, loc) {} public: void operator delete(void *Ptr, size_t) = delete; @@ -1288,7 +1221,7 @@ class MultipleValueInstruction : public NonSingleValueInstruction { unsigned getNumResults() const { return getResults().size(); } - static bool classof(SILNodePointer node) { + static bool classof(const SILNode *node) { SILNodeKind kind = node->getKind(); return kind >= SILNodeKind::First_MultipleValueInstruction && kind <= SILNodeKind::Last_MultipleValueInstruction; @@ -1421,25 +1354,25 @@ class MultipleValueInstructionTrailingObjectsgetKind() >= SILNodeKind::First_NonValueInstruction && - node->getKind() <= SILNodeKind::Last_NonValueInstruction; + static bool classof(const SILNode *N) { + return N->getKind() >= SILNodeKind::First_NonValueInstruction && + N->getKind() <= SILNodeKind::Last_NonValueInstruction; } static bool classof(const NonValueInstruction *) { return true; } }; #define DEFINE_ABSTRACT_NON_VALUE_INST_BOILERPLATE(ID) \ static bool classof(const ValueBase *value) = delete; \ - static bool classof(SILNodePointer node) { \ + static bool classof(const SILNode *node) { \ return node->getKind() >= SILNodeKind::First_##ID && \ node->getKind() <= SILNodeKind::Last_##ID; \ } @@ -1462,9 +1395,12 @@ class InstructionBase : public InstBase { return Kind; } - static bool classof(SILNodePointer node) { + static bool classof(const SILNode *node) { return node->getKind() == SILNodeKind(Kind); } + static bool classof(const SingleValueInstruction *I) { // resolve ambiguities + return I->getKind() == Kind; + } }; template @@ -1481,7 +1417,7 @@ class InstructionBase : public InstBase { /// Can never dynamically succeed. static bool classof(const ValueBase *value) = delete; - static bool classof(SILNodePointer node) { + static bool classof(const SILNode *node) { return node->getKind() == SILNodeKind(Kind); } }; @@ -1540,7 +1476,7 @@ class InstructionBaseWithTrailingOperands InstructionBaseWithTrailingOperands(ArrayRef Operands, Args &&...args) : InstructionBase(std::forward(args)...) { - SILNode::Bits.IBWTO.NumOperands = Operands.size(); + SILInstruction::Bits.IBWTO.NumOperands = Operands.size(); TrailingOperandsList::InitOperandsList(getAllOperands().begin(), this, Operands); } @@ -1550,7 +1486,7 @@ class InstructionBaseWithTrailingOperands ArrayRef Operands, Args &&...args) : InstructionBase(std::forward(args)...) { - SILNode::Bits.IBWTO.NumOperands = Operands.size() + 1; + SILInstruction::Bits.IBWTO.NumOperands = Operands.size() + 1; TrailingOperandsList::InitOperandsList(getAllOperands().begin(), this, Operand0, Operands); } @@ -1561,7 +1497,7 @@ class InstructionBaseWithTrailingOperands ArrayRef Operands, Args &&...args) : InstructionBase(std::forward(args)...) { - SILNode::Bits.IBWTO.NumOperands = Operands.size() + 2; + SILInstruction::Bits.IBWTO.NumOperands = Operands.size() + 2; TrailingOperandsList::InitOperandsList(getAllOperands().begin(), this, Operand0, Operand1, Operands); } @@ -1569,7 +1505,7 @@ class InstructionBaseWithTrailingOperands // Destruct tail allocated objects. ~InstructionBaseWithTrailingOperands() { Operand *Operands = TrailingObjects::template getTrailingObjects(); - auto end = SILNode::Bits.IBWTO.NumOperands; + auto end = SILInstruction::Bits.IBWTO.NumOperands; for (unsigned i = 0; i < end; ++i) { Operands[i].~Operand(); } @@ -1577,17 +1513,17 @@ class InstructionBaseWithTrailingOperands size_t numTrailingObjects(typename TrailingObjects::template OverloadToken) const { - return SILNode::Bits.IBWTO.NumOperands; + return SILInstruction::Bits.IBWTO.NumOperands; } ArrayRef getAllOperands() const { return {TrailingObjects::template getTrailingObjects(), - SILNode::Bits.IBWTO.NumOperands}; + SILInstruction::Bits.IBWTO.NumOperands}; } MutableArrayRef getAllOperands() { return {TrailingObjects::template getTrailingObjects(), - SILNode::Bits.IBWTO.NumOperands}; + SILInstruction::Bits.IBWTO.NumOperands}; } }; @@ -1755,13 +1691,13 @@ class AllocStackInst final bool hasDynamicLifetime); size_t numTrailingObjects(OverloadToken) const { - return SILNode::Bits.AllocStackInst.NumOperands; + return SILInstruction::Bits.AllocStackInst.NumOperands; } public: ~AllocStackInst() { Operand *Operands = getTrailingObjects(); - size_t end = SILNode::Bits.AllocStackInst.NumOperands; + size_t end = SILInstruction::Bits.AllocStackInst.NumOperands; for (unsigned i = 0; i < end; ++i) { Operands[i].~Operand(); } @@ -1783,15 +1719,15 @@ class AllocStackInst final /// Return the debug variable information attached to this instruction. Optional getVarInfo() const { - auto RawValue = SILNode::Bits.AllocStackInst.VarInfo; + auto RawValue = SILInstruction::Bits.AllocStackInst.VarInfo; auto VI = TailAllocatedDebugVariable(RawValue); return VI.get(getDecl(), getTrailingObjects()); }; void setArgNo(unsigned N) { - auto RawValue = SILNode::Bits.AllocStackInst.VarInfo; + auto RawValue = SILInstruction::Bits.AllocStackInst.VarInfo; auto VI = TailAllocatedDebugVariable(RawValue); VI.setArgNo(N); - SILNode::Bits.AllocStackInst.VarInfo = VI.getRawValue(); + SILInstruction::Bits.AllocStackInst.VarInfo = VI.getRawValue(); } /// getElementType - Get the type of the allocated memory (as opposed to the @@ -1802,12 +1738,12 @@ class AllocStackInst final ArrayRef getAllOperands() const { return { getTrailingObjects(), - static_cast(SILNode::Bits.AllocStackInst.NumOperands) }; + static_cast(SILInstruction::Bits.AllocStackInst.NumOperands) }; } MutableArrayRef getAllOperands() { return { getTrailingObjects(), - static_cast(SILNode::Bits.AllocStackInst.NumOperands) }; + static_cast(SILInstruction::Bits.AllocStackInst.NumOperands) }; } ArrayRef getTypeDependentOperands() const { @@ -1841,16 +1777,16 @@ class AllocRefInstBase : public AllocationInst { } unsigned getNumTailTypes() const { - return SILNode::Bits.AllocRefInstBase.NumTailTypes; + return SILInstruction::Bits.AllocRefInstBase.NumTailTypes; } public: bool canAllocOnStack() const { - return SILNode::Bits.AllocRefInstBase.OnStack; + return SILInstruction::Bits.AllocRefInstBase.OnStack; } void setStackAllocatable(bool OnStack = true) { - SILNode::Bits.AllocRefInstBase.OnStack = OnStack; + SILInstruction::Bits.AllocRefInstBase.OnStack = OnStack; } ArrayRef getTailAllocatedTypes() const { @@ -1874,7 +1810,7 @@ class AllocRefInstBase : public AllocationInst { /// Whether to use Objective-C's allocation mechanism (+allocWithZone:). bool isObjC() const { - return SILNode::Bits.AllocRefInstBase.ObjC; + return SILInstruction::Bits.AllocRefInstBase.ObjC; } }; @@ -2604,8 +2540,8 @@ class BeginApplyResult final : public MultipleValueInstructionResult { /// over the implicit coroutine state? bool isTokenResult() const; // inline below - static bool classof(SILNodePointer node) { - return node->getKind() == SILNodeKind::BeginApplyResult; + static bool classof(const SILNode *N) { + return N->getKind() == SILNodeKind::BeginApplyResult; } }; @@ -2779,11 +2715,16 @@ class FunctionRefBaseInst : public LiteralInst { ArrayRef getAllOperands() const { return {}; } MutableArrayRef getAllOperands() { return {}; } - static bool classof(SILNodePointer node) { + static bool classof(const SILNode *node) { return (node->getKind() == SILNodeKind::FunctionRefInst || node->getKind() == SILNodeKind::DynamicFunctionRefInst || node->getKind() == SILNodeKind::PreviousDynamicFunctionRefInst); } + static bool classof(const SingleValueInstruction *node) { + return (node->getKind() == SILInstructionKind::FunctionRefInst || + node->getKind() == SILInstructionKind::DynamicFunctionRefInst || + node->getKind() == SILInstructionKind::PreviousDynamicFunctionRefInst); + } }; /// FunctionRefInst - Represents a reference to a SIL function. @@ -2799,9 +2740,12 @@ class FunctionRefInst : public FunctionRefBaseInst { TypeExpansionContext context); public: - static bool classof(SILNodePointer node) { + static bool classof(const SILNode *node) { return node->getKind() == SILNodeKind::FunctionRefInst; } + static bool classof(const SingleValueInstruction *node) { + return node->getKind() == SILInstructionKind::FunctionRefInst; + } }; class DynamicFunctionRefInst : public FunctionRefBaseInst { @@ -2816,9 +2760,12 @@ class DynamicFunctionRefInst : public FunctionRefBaseInst { TypeExpansionContext context); public: - static bool classof(SILNodePointer node) { + static bool classof(const SILNode *node) { return node->getKind() == SILNodeKind::DynamicFunctionRefInst; } + static bool classof(const SingleValueInstruction *node) { + return node->getKind() == SILInstructionKind::DynamicFunctionRefInst; + } }; class PreviousDynamicFunctionRefInst : public FunctionRefBaseInst { @@ -2833,9 +2780,13 @@ class PreviousDynamicFunctionRefInst : public FunctionRefBaseInst { TypeExpansionContext context); public: - static bool classof(SILNodePointer node) { + static bool classof(const SILNode *node) { return node->getKind() == SILNodeKind::PreviousDynamicFunctionRefInst; } + static bool classof(const SingleValueInstruction *node) { + return node->getKind() == + SILInstructionKind::PreviousDynamicFunctionRefInst; + } }; /// Component of a KeyPathInst. @@ -3367,9 +3318,9 @@ class GetAsyncContinuationInstBase /// True if the continuation can be used to resume the task by throwing an error. bool throws() const { return Throws; } - static bool classof(SILNodePointer node) { - return node->getKind() >= SILNodeKind::First_GetAsyncContinuationInstBase && - node->getKind() <= SILNodeKind::Last_GetAsyncContinuationInstBase; + static bool classof(const SILNode *I) { + return I->getKind() >= SILNodeKind::First_GetAsyncContinuationInstBase && + I->getKind() <= SILNodeKind::Last_GetAsyncContinuationInstBase; } }; @@ -3544,7 +3495,7 @@ class BuiltinInst final /// usages of the global via GlobalAddrInst. class AllocGlobalInst : public InstructionBase { + SILInstruction> { friend SILBuilder; SILGlobalVariable *Global; @@ -3708,12 +3659,12 @@ class StringLiteralInst final /// getValue - Return the string data for the literal, in UTF-8. StringRef getValue() const { return {getTrailingObjects(), - SILNode::Bits.StringLiteralInst.Length}; + SILInstruction::Bits.StringLiteralInst.Length}; } /// getEncoding - Return the desired encoding of the text. Encoding getEncoding() const { - return Encoding(SILNode::Bits.StringLiteralInst.TheEncoding); + return Encoding(SILInstruction::Bits.StringLiteralInst.TheEncoding); } /// getCodeUnitCount - Return encoding-based length of the string @@ -3757,16 +3708,16 @@ class LoadInst LoadOwnershipQualifier Q = LoadOwnershipQualifier::Unqualified) : UnaryInstructionBase(DebugLoc, LValue, LValue->getType().getObjectType()) { - SILNode::Bits.LoadInst.OwnershipQualifier = unsigned(Q); + SILInstruction::Bits.LoadInst.OwnershipQualifier = unsigned(Q); } public: LoadOwnershipQualifier getOwnershipQualifier() const { return LoadOwnershipQualifier( - SILNode::Bits.LoadInst.OwnershipQualifier); + SILInstruction::Bits.LoadInst.OwnershipQualifier); } void setOwnershipQualifier(LoadOwnershipQualifier qualifier) { - SILNode::Bits.LoadInst.OwnershipQualifier = unsigned(qualifier); + SILInstruction::Bits.LoadInst.OwnershipQualifier = unsigned(qualifier); } }; @@ -3805,10 +3756,10 @@ class StoreInst StoreOwnershipQualifier getOwnershipQualifier() const { return StoreOwnershipQualifier( - SILNode::Bits.StoreInst.OwnershipQualifier); + SILInstruction::Bits.StoreInst.OwnershipQualifier); } void setOwnershipQualifier(StoreOwnershipQualifier qualifier) { - SILNode::Bits.StoreInst.OwnershipQualifier = unsigned(qualifier); + SILInstruction::Bits.StoreInst.OwnershipQualifier = unsigned(qualifier); } }; @@ -4017,11 +3968,11 @@ class BeginAccessInst SILAccessKind accessKind, SILAccessEnforcement enforcement, bool noNestedConflict, bool fromBuiltin) : UnaryInstructionBase(loc, lvalue, lvalue->getType()) { - SILNode::Bits.BeginAccessInst.AccessKind = unsigned(accessKind); - SILNode::Bits.BeginAccessInst.Enforcement = unsigned(enforcement); - SILNode::Bits.BeginAccessInst.NoNestedConflict = + SILInstruction::Bits.BeginAccessInst.AccessKind = unsigned(accessKind); + SILInstruction::Bits.BeginAccessInst.Enforcement = unsigned(enforcement); + SILInstruction::Bits.BeginAccessInst.NoNestedConflict = unsigned(noNestedConflict); - SILNode::Bits.BeginAccessInst.FromBuiltin = + SILInstruction::Bits.BeginAccessInst.FromBuiltin = unsigned(fromBuiltin); static_assert(unsigned(SILAccessKind::Last) < (1 << 2), @@ -4039,18 +3990,18 @@ class BeginAccessInst public: SILAccessKind getAccessKind() const { - return SILAccessKind(SILNode::Bits.BeginAccessInst.AccessKind); + return SILAccessKind(SILInstruction::Bits.BeginAccessInst.AccessKind); } void setAccessKind(SILAccessKind kind) { - SILNode::Bits.BeginAccessInst.AccessKind = unsigned(kind); + SILInstruction::Bits.BeginAccessInst.AccessKind = unsigned(kind); } SILAccessEnforcement getEnforcement() const { return - SILAccessEnforcement(SILNode::Bits.BeginAccessInst.Enforcement); + SILAccessEnforcement(SILInstruction::Bits.BeginAccessInst.Enforcement); } void setEnforcement(SILAccessEnforcement enforcement) { - SILNode::Bits.BeginAccessInst.Enforcement = unsigned(enforcement); + SILInstruction::Bits.BeginAccessInst.Enforcement = unsigned(enforcement); } /// If hasNoNestedConflict is true, then it is a static guarantee against @@ -4060,17 +4011,17 @@ class BeginAccessInst /// its scope. This access may still conflict with an outer access scope; /// therefore may still require dynamic enforcement at a single point. bool hasNoNestedConflict() const { - return SILNode::Bits.BeginAccessInst.NoNestedConflict; + return SILInstruction::Bits.BeginAccessInst.NoNestedConflict; } void setNoNestedConflict(bool noNestedConflict) { - SILNode::Bits.BeginAccessInst.NoNestedConflict = noNestedConflict; + SILInstruction::Bits.BeginAccessInst.NoNestedConflict = noNestedConflict; } /// Return true if this access marker was emitted for a user-controlled /// Builtin. Return false if this access marker was auto-generated by the /// compiler to enforce formal access that derives from the language. bool isFromBuiltin() const { - return SILNode::Bits.BeginAccessInst.FromBuiltin; + return SILInstruction::Bits.BeginAccessInst.FromBuiltin; } SILValue getSource() const { @@ -4093,7 +4044,7 @@ class EndAccessInst private: EndAccessInst(SILDebugLocation loc, SILValue access, bool aborting = false) : UnaryInstructionBase(loc, access) { - SILNode::Bits.EndAccessInst.Aborting = aborting; + SILInstruction::Bits.EndAccessInst.Aborting = aborting; } public: @@ -4104,10 +4055,10 @@ class EndAccessInst /// Only AccessKind::Init and AccessKind::Deinit accesses can be /// aborted. bool isAborting() const { - return SILNode::Bits.EndAccessInst.Aborting; + return SILInstruction::Bits.EndAccessInst.Aborting; } void setAborting(bool aborting = true) { - SILNode::Bits.EndAccessInst.Aborting = aborting; + SILInstruction::Bits.EndAccessInst.Aborting = aborting; } BeginAccessInst *getBeginAccess() const { @@ -4141,31 +4092,31 @@ class BeginUnpairedAccessInst bool noNestedConflict, bool fromBuiltin) : InstructionBase(loc), Operands(this, addr, buffer) { - SILNode::Bits.BeginUnpairedAccessInst.AccessKind = + SILInstruction::Bits.BeginUnpairedAccessInst.AccessKind = unsigned(accessKind); - SILNode::Bits.BeginUnpairedAccessInst.Enforcement = + SILInstruction::Bits.BeginUnpairedAccessInst.Enforcement = unsigned(enforcement); - SILNode::Bits.BeginUnpairedAccessInst.NoNestedConflict = + SILInstruction::Bits.BeginUnpairedAccessInst.NoNestedConflict = unsigned(noNestedConflict); - SILNode::Bits.BeginUnpairedAccessInst.FromBuiltin = + SILInstruction::Bits.BeginUnpairedAccessInst.FromBuiltin = unsigned(fromBuiltin); } public: SILAccessKind getAccessKind() const { return SILAccessKind( - SILNode::Bits.BeginUnpairedAccessInst.AccessKind); + SILInstruction::Bits.BeginUnpairedAccessInst.AccessKind); } void setAccessKind(SILAccessKind kind) { - SILNode::Bits.BeginUnpairedAccessInst.AccessKind = unsigned(kind); + SILInstruction::Bits.BeginUnpairedAccessInst.AccessKind = unsigned(kind); } SILAccessEnforcement getEnforcement() const { return SILAccessEnforcement( - SILNode::Bits.BeginUnpairedAccessInst.Enforcement); + SILInstruction::Bits.BeginUnpairedAccessInst.Enforcement); } void setEnforcement(SILAccessEnforcement enforcement) { - SILNode::Bits.BeginUnpairedAccessInst.Enforcement + SILInstruction::Bits.BeginUnpairedAccessInst.Enforcement = unsigned(enforcement); } @@ -4176,10 +4127,10 @@ class BeginUnpairedAccessInst /// its scope. This access may still conflict with an outer access scope; /// therefore may still require dynamic enforcement at a single point. bool hasNoNestedConflict() const { - return SILNode::Bits.BeginUnpairedAccessInst.NoNestedConflict; + return SILInstruction::Bits.BeginUnpairedAccessInst.NoNestedConflict; } void setNoNestedConflict(bool noNestedConflict) { - SILNode::Bits.BeginUnpairedAccessInst.NoNestedConflict = + SILInstruction::Bits.BeginUnpairedAccessInst.NoNestedConflict = noNestedConflict; } @@ -4187,7 +4138,7 @@ class BeginUnpairedAccessInst /// Builtin. Return false if this access marker was auto-generated by the /// compiler to enforce formal access that derives from the language. bool isFromBuiltin() const { - return SILNode::Bits.BeginUnpairedAccessInst.FromBuiltin; + return SILInstruction::Bits.BeginUnpairedAccessInst.FromBuiltin; } SILValue getSource() const { @@ -4221,10 +4172,10 @@ class EndUnpairedAccessInst SILAccessEnforcement enforcement, bool aborting, bool fromBuiltin) : UnaryInstructionBase(loc, buffer) { - SILNode::Bits.EndUnpairedAccessInst.Enforcement + SILInstruction::Bits.EndUnpairedAccessInst.Enforcement = unsigned(enforcement); - SILNode::Bits.EndUnpairedAccessInst.Aborting = aborting; - SILNode::Bits.EndUnpairedAccessInst.FromBuiltin = fromBuiltin; + SILInstruction::Bits.EndUnpairedAccessInst.Aborting = aborting; + SILInstruction::Bits.EndUnpairedAccessInst.FromBuiltin = fromBuiltin; } public: @@ -4235,18 +4186,18 @@ class EndUnpairedAccessInst /// Only AccessKind::Init and AccessKind::Deinit accesses can be /// aborted. bool isAborting() const { - return SILNode::Bits.EndUnpairedAccessInst.Aborting; + return SILInstruction::Bits.EndUnpairedAccessInst.Aborting; } void setAborting(bool aborting) { - SILNode::Bits.EndUnpairedAccessInst.Aborting = aborting; + SILInstruction::Bits.EndUnpairedAccessInst.Aborting = aborting; } SILAccessEnforcement getEnforcement() const { return SILAccessEnforcement( - SILNode::Bits.EndUnpairedAccessInst.Enforcement); + SILInstruction::Bits.EndUnpairedAccessInst.Enforcement); } void setEnforcement(SILAccessEnforcement enforcement) { - SILNode::Bits.EndUnpairedAccessInst.Enforcement = + SILInstruction::Bits.EndUnpairedAccessInst.Enforcement = unsigned(enforcement); } @@ -4254,7 +4205,7 @@ class EndUnpairedAccessInst /// Builtin. Return false if this access marker was auto-generated by the /// compiler to enforce formal access that derives from the language. bool isFromBuiltin() const { - return SILNode::Bits.EndUnpairedAccessInst.FromBuiltin; + return SILInstruction::Bits.EndUnpairedAccessInst.FromBuiltin; } SILValue getBuffer() const { @@ -4322,10 +4273,10 @@ class AssignInst public: AssignOwnershipQualifier getOwnershipQualifier() const { return AssignOwnershipQualifier( - SILNode::Bits.AssignInst.OwnershipQualifier); + SILInstruction::Bits.AssignInst.OwnershipQualifier); } void setOwnershipQualifier(AssignOwnershipQualifier qualifier) { - SILNode::Bits.AssignInst.OwnershipQualifier = unsigned(qualifier); + SILInstruction::Bits.AssignInst.OwnershipQualifier = unsigned(qualifier); } }; @@ -4358,7 +4309,7 @@ class AssignByWrapperInst AssignOwnershipQualifier getOwnershipQualifier() const { return AssignOwnershipQualifier( - SILNode::Bits.AssignByWrapperInst.OwnershipQualifier); + SILInstruction::Bits.AssignByWrapperInst.OwnershipQualifier); } Destination getAssignDestination() const { return AssignDest; } @@ -4368,7 +4319,7 @@ class AssignByWrapperInst qualifier == AssignOwnershipQualifier::Reassign && dest == Destination::BackingWrapper || qualifier == AssignOwnershipQualifier::Reassign && dest == Destination::WrappedValue); - SILNode::Bits.AssignByWrapperInst.OwnershipQualifier = unsigned(qualifier); + SILInstruction::Bits.AssignByWrapperInst.OwnershipQualifier = unsigned(qualifier); AssignDest = dest; } }; @@ -4544,12 +4495,12 @@ class LoadReferenceInstBase LoadReferenceInstBase(SILDebugLocation loc, SILValue lvalue, IsTake_t isTake) : UnaryInstructionBase(loc, lvalue, getResultType(lvalue->getType())) { - SILNode::Bits.LoadReferenceInstBaseT.IsTake = unsigned(isTake); + SILInstruction::Bits.LoadReferenceInstBaseT.IsTake = unsigned(isTake); } public: IsTake_t isTake() const { - return IsTake_t(SILNode::Bits.LoadReferenceInstBaseT.IsTake); + return IsTake_t(SILInstruction::Bits.LoadReferenceInstBaseT.IsTake); } }; @@ -4563,7 +4514,7 @@ class StoreReferenceInstBase : public InstructionBase { IsInitialization_t isInit) : InstructionBase(loc), Operands(this, src, dest) { - SILNode::Bits.StoreReferenceInstBaseT.IsInitializationOfDest = + SILInstruction::Bits.StoreReferenceInstBaseT.IsInitializationOfDest = unsigned(isInit); } @@ -4573,10 +4524,10 @@ class StoreReferenceInstBase : public InstructionBase { IsInitialization_t isInitializationOfDest() const { return IsInitialization_t( - SILNode::Bits.StoreReferenceInstBaseT.IsInitializationOfDest); + SILInstruction::Bits.StoreReferenceInstBaseT.IsInitializationOfDest); } void setIsInitializationOfDest(IsInitialization_t I) { - SILNode::Bits.StoreReferenceInstBaseT.IsInitializationOfDest = + SILInstruction::Bits.StoreReferenceInstBaseT.IsInitializationOfDest = (bool)I; } @@ -4646,18 +4597,18 @@ class CopyAddrInst void setDest(SILValue V) { Operands[Dest].set(V); } IsTake_t isTakeOfSrc() const { - return IsTake_t(SILNode::Bits.CopyAddrInst.IsTakeOfSrc); + return IsTake_t(SILInstruction::Bits.CopyAddrInst.IsTakeOfSrc); } IsInitialization_t isInitializationOfDest() const { return IsInitialization_t( - SILNode::Bits.CopyAddrInst.IsInitializationOfDest); + SILInstruction::Bits.CopyAddrInst.IsInitializationOfDest); } void setIsTakeOfSrc(IsTake_t T) { - SILNode::Bits.CopyAddrInst.IsTakeOfSrc = (bool)T; + SILInstruction::Bits.CopyAddrInst.IsTakeOfSrc = (bool)T; } void setIsInitializationOfDest(IsInitialization_t I) { - SILNode::Bits.CopyAddrInst.IsInitializationOfDest = (bool)I; + SILInstruction::Bits.CopyAddrInst.IsInitializationOfDest = (bool)I; } ArrayRef getAllOperands() const { return Operands.asArray(); } @@ -4740,8 +4691,8 @@ class OwnershipForwardingConversionInst : public ConversionInst, } public: - static bool classof(SILNodePointer node) { - if (auto *i = dyn_cast(node.get())) + static bool classof(const SILNode *node) { + if (auto *i = dyn_cast(node)) return classof(i); return false; } @@ -4781,7 +4732,7 @@ class ConvertFunctionInst final : UnaryInstructionWithTypeDependentOperandsBase( DebugLoc, Operand, TypeDependentOperands, Ty, Operand.getOwnershipKind()) { - SILNode::Bits.ConvertFunctionInst.WithoutActuallyEscaping = + SILInstruction::Bits.ConvertFunctionInst.WithoutActuallyEscaping = WithoutActuallyEscaping; assert((Operand->getType().castTo()->isNoEscape() == Ty.castTo()->isNoEscape() || @@ -4806,7 +4757,7 @@ class ConvertFunctionInst final /// not be @noescape. Note that a non-escaping closure may have unboxed /// captured even though its SIL function type is "escaping". bool withoutActuallyEscaping() const { - return SILNode::Bits.ConvertFunctionInst.WithoutActuallyEscaping; + return SILInstruction::Bits.ConvertFunctionInst.WithoutActuallyEscaping; } /// Returns `true` if the function conversion is between types with the same @@ -4925,8 +4876,8 @@ class PointerToAddressInst PointerToAddressInst(SILDebugLocation DebugLoc, SILValue Operand, SILType Ty, bool IsStrict, bool IsInvariant) : UnaryInstructionBase(DebugLoc, Operand, Ty) { - SILNode::Bits.PointerToAddressInst.IsStrict = IsStrict; - SILNode::Bits.PointerToAddressInst.IsInvariant = IsInvariant; + SILInstruction::Bits.PointerToAddressInst.IsStrict = IsStrict; + SILInstruction::Bits.PointerToAddressInst.IsInvariant = IsInvariant; } public: @@ -4934,13 +4885,13 @@ class PointerToAddressInst /// If true, then the type of each memory access dependent on /// this address must be consistent with the memory's bound type. bool isStrict() const { - return SILNode::Bits.PointerToAddressInst.IsStrict; + return SILInstruction::Bits.PointerToAddressInst.IsStrict; } /// Whether the returned address is invariant. /// If true, then loading from an address derived from this pointer always /// produces the same value. bool isInvariant() const { - return SILNode::Bits.PointerToAddressInst.IsInvariant; + return SILInstruction::Bits.PointerToAddressInst.IsInvariant; } }; @@ -5390,21 +5341,21 @@ class RefCountingInst : public NonValueInstruction { protected: RefCountingInst(SILInstructionKind Kind, SILDebugLocation DebugLoc) : NonValueInstruction(Kind, DebugLoc) { - SILNode::Bits.RefCountingInst.atomicity = bool(Atomicity::Atomic); + SILInstruction::Bits.RefCountingInst.atomicity = bool(Atomicity::Atomic); } public: void setAtomicity(Atomicity flag) { - SILNode::Bits.RefCountingInst.atomicity = bool(flag); + SILInstruction::Bits.RefCountingInst.atomicity = bool(flag); } void setNonAtomic() { - SILNode::Bits.RefCountingInst.atomicity = bool(Atomicity::NonAtomic); + SILInstruction::Bits.RefCountingInst.atomicity = bool(Atomicity::NonAtomic); } void setAtomic() { - SILNode::Bits.RefCountingInst.atomicity = bool(Atomicity::Atomic); + SILInstruction::Bits.RefCountingInst.atomicity = bool(Atomicity::Atomic); } Atomicity getAtomicity() const { - return Atomicity(SILNode::Bits.RefCountingInst.atomicity); + return Atomicity(SILInstruction::Bits.RefCountingInst.atomicity); } bool isNonAtomic() const { return getAtomicity() == Atomicity::NonAtomic; } bool isAtomic() const { return getAtomicity() == Atomicity::Atomic; } @@ -5554,7 +5505,7 @@ class ObjectInst final : public InstructionBaseWithTrailingOperands< Elements, DebugLoc, Ty, HasOwnership ? mergeSILValueOwnership(Elements) : ValueOwnershipKind(OwnershipKind::None)) { - SILNode::Bits.ObjectInst.NumBaseElements = NumBaseElements; + SILInstruction::Bits.ObjectInst.NumBaseElements = NumBaseElements; } /// Construct an ObjectInst. @@ -5577,13 +5528,13 @@ class ObjectInst final : public InstructionBaseWithTrailingOperands< /// The elements which initialize the stored properties of the object itself. OperandValueArrayRef getBaseElements() const { return OperandValueArrayRef(getAllOperands().slice(0, - SILNode::Bits.ObjectInst.NumBaseElements)); + SILInstruction::Bits.ObjectInst.NumBaseElements)); } /// The elements which initialize the tail allocated elements. OperandValueArrayRef getTailElements() const { return OperandValueArrayRef(getAllOperands().slice( - SILNode::Bits.ObjectInst.NumBaseElements)); + SILInstruction::Bits.ObjectInst.NumBaseElements)); } }; @@ -5871,7 +5822,7 @@ class SelectEnumInstBase Optional> CaseCounts, ProfileCounter DefaultCount) : SelectInstBase(kind, debugLoc, type) { - SILNode::Bits.SelectEnumInstBase.HasDefault = defaultValue; + SILInstruction::Bits.SelectEnumInstBase.HasDefault = defaultValue; } template static SELECT_ENUM_INST * @@ -5910,7 +5861,7 @@ class SelectEnumInstBase NullablePtr getUniqueCaseForDefault(); bool hasDefault() const { - return SILNode::Bits.SelectEnumInstBase.HasDefault; + return SILInstruction::Bits.SelectEnumInstBase.HasDefault; } SILValue getDefaultResult() const { @@ -5946,8 +5897,8 @@ class OwnershipForwardingSelectEnumInstBase : public SelectEnumInstBase, } public: - static bool classof(SILNodePointer node) { - if (auto *i = dyn_cast(node.get())) + static bool classof(const SILNode *node) { + if (auto *i = dyn_cast(node)) return classof(i); return false; } @@ -6134,12 +6085,12 @@ class TupleExtractInst unsigned FieldNo, SILType ResultTy) : UnaryInstructionBase(DebugLoc, Operand, ResultTy, Operand.getOwnershipKind()) { - SILNode::Bits.TupleExtractInst.FieldNo = FieldNo; + SILInstruction::Bits.TupleExtractInst.FieldNo = FieldNo; } public: unsigned getFieldIndex() const { - return SILNode::Bits.TupleExtractInst.FieldNo; + return SILInstruction::Bits.TupleExtractInst.FieldNo; } TupleType *getTupleType() const { @@ -6166,12 +6117,12 @@ class TupleElementAddrInst TupleElementAddrInst(SILDebugLocation DebugLoc, SILValue Operand, unsigned FieldNo, SILType ResultTy) : UnaryInstructionBase(DebugLoc, Operand, ResultTy) { - SILNode::Bits.TupleElementAddrInst.FieldNo = FieldNo; + SILInstruction::Bits.TupleElementAddrInst.FieldNo = FieldNo; } public: unsigned getFieldIndex() const { - return SILNode::Bits.TupleElementAddrInst.FieldNo; + return SILInstruction::Bits.TupleElementAddrInst.FieldNo; } @@ -6227,7 +6178,7 @@ class FieldIndexCacheBase : public ParentTy { SILType type, VarDecl *field, ArgTys &&... extraArgs) : ParentTy(kind, loc, type, std::forward(extraArgs)...), field(field) { - SILNode::Bits.FieldIndexCacheBase.FieldIndex = InvalidFieldIndex; + SILInstruction::Bits.FieldIndexCacheBase.FieldIndex = InvalidFieldIndex; // This needs to be a concrete class to hold bitfield information. However, // it should only be extended by UnaryInstructions. assert(ParentTy::getNumOperands() == 1); @@ -6236,7 +6187,7 @@ class FieldIndexCacheBase : public ParentTy { VarDecl *getField() const { return field; } unsigned getFieldIndex() const { - unsigned idx = SILNode::Bits.FieldIndexCacheBase.FieldIndex; + unsigned idx = SILInstruction::Bits.FieldIndexCacheBase.FieldIndex; if (idx != InvalidFieldIndex) return idx; @@ -6250,7 +6201,7 @@ class FieldIndexCacheBase : public ParentTy { return s; } - static bool classof(SILNodePointer node) { + static bool classof(const SILNode *node) { SILNodeKind kind = node->getKind(); return kind == SILNodeKind::StructExtractInst || kind == SILNodeKind::StructElementAddrInst || @@ -6260,7 +6211,7 @@ class FieldIndexCacheBase : public ParentTy { private: unsigned cacheFieldIndex() { unsigned index = swift::getFieldIndex(getParentDecl(), getField()); - SILNode::Bits.FieldIndexCacheBase.FieldIndex = index; + SILInstruction::Bits.FieldIndexCacheBase.FieldIndex = index; return index; } }; @@ -6327,12 +6278,12 @@ class RefElementAddrInst /// Returns true if all loads of the same instance variable from the same /// class reference operand are guaranteed to yield the same value. bool isImmutable() const { - return SILNode::Bits.RefElementAddrInst.Immutable; + return SILInstruction::Bits.RefElementAddrInst.Immutable; } /// Sets the immutable flag. void setImmutable(bool immutable = true) { - SILNode::Bits.RefElementAddrInst.Immutable = immutable; + SILInstruction::Bits.RefElementAddrInst.Immutable = immutable; } }; @@ -6362,12 +6313,12 @@ class RefTailAddrInst /// Returns true if all loads of the same instance variable from the same /// class reference operand are guaranteed to yield the same value. bool isImmutable() const { - return SILNode::Bits.RefTailAddrInst.Immutable; + return SILInstruction::Bits.RefTailAddrInst.Immutable; } /// Sets the immutable flag. void setImmutable(bool immutable = true) { - SILNode::Bits.RefTailAddrInst.Immutable = immutable; + SILInstruction::Bits.RefTailAddrInst.Immutable = immutable; } }; @@ -6942,12 +6893,12 @@ class UncheckedOwnershipConversionInst UncheckedOwnershipConversionInst(SILDebugLocation DebugLoc, SILValue operand, ValueOwnershipKind Kind) : UnaryInstructionBase(DebugLoc, operand, operand->getType()) { - SILNode::Bits.UncheckedOwnershipConversionInst.Kind = Kind; + SILInstruction::Bits.UncheckedOwnershipConversionInst.Kind = Kind; } public: ValueOwnershipKind getConversionOwnershipKind() const { - unsigned kind = SILNode::Bits.UncheckedOwnershipConversionInst.Kind; + unsigned kind = SILInstruction::Bits.UncheckedOwnershipConversionInst.Kind; return ValueOwnershipKind(kind); } }; @@ -7115,8 +7066,8 @@ class BeginCOWMutationResult final : public MultipleValueInstructionResult { return const_cast(this)->getParent(); } - static bool classof(SILNodePointer node) { - return node->getKind() == SILNodeKind::BeginCOWMutationResult; + static bool classof(const SILNode *N) { + return N->getKind() == SILNodeKind::BeginCOWMutationResult; } }; @@ -7158,11 +7109,11 @@ class BeginCOWMutationInst final } bool isNative() const { - return SILNode::Bits.BeginCOWMutationInst.Native; + return SILInstruction::Bits.BeginCOWMutationInst.Native; } void setNative(bool native = true) { - SILNode::Bits.BeginCOWMutationInst.Native = native; + SILInstruction::Bits.BeginCOWMutationInst.Native = native; } }; @@ -7187,11 +7138,11 @@ class EndCOWMutationInst public: bool doKeepUnique() const { - return SILNode::Bits.EndCOWMutationInst.KeepUnique; + return SILInstruction::Bits.EndCOWMutationInst.KeepUnique; } void setKeepUnique(bool keepUnique = true) { - SILNode::Bits.EndCOWMutationInst.KeepUnique = keepUnique; + SILInstruction::Bits.EndCOWMutationInst.KeepUnique = keepUnique; } }; @@ -7256,16 +7207,16 @@ class DeallocRefInst : DeallocRefInst(SILDebugLocation DebugLoc, SILValue Operand, bool canBeOnStack = false) : UnaryInstructionBase(DebugLoc, Operand) { - SILNode::Bits.DeallocRefInst.OnStack = canBeOnStack; + SILInstruction::Bits.DeallocRefInst.OnStack = canBeOnStack; } public: bool canAllocOnStack() const { - return SILNode::Bits.DeallocRefInst.OnStack; + return SILInstruction::Bits.DeallocRefInst.OnStack; } void setStackAllocatable(bool OnStack) { - SILNode::Bits.DeallocRefInst.OnStack = OnStack; + SILInstruction::Bits.DeallocRefInst.OnStack = OnStack; } }; @@ -7684,8 +7635,8 @@ class OwnershipForwardingTermInst : public TermInst, } public: - static bool classof(SILNodePointer node) { - if (auto *i = dyn_cast(node.get())) + static bool classof(const SILNode *node) { + if (auto *i = dyn_cast(node)) return classof(i); return false; } @@ -7975,12 +7926,12 @@ class CondBranchInst final /// The number of arguments for the True branch. unsigned getNumTrueArgs() const { - return SILNode::Bits.CondBranchInst.NumTrueArgs; + return SILInstruction::Bits.CondBranchInst.NumTrueArgs; } /// The number of arguments for the False branch. unsigned getNumFalseArgs() const { return getAllOperands().size() - NumFixedOpers - - SILNode::Bits.CondBranchInst.NumTrueArgs; + SILInstruction::Bits.CondBranchInst.NumTrueArgs; } CondBranchInst(SILDebugLocation DebugLoc, SILValue Condition, @@ -8186,7 +8137,7 @@ class SwitchValueInst final } bool hasDefault() const { - return SILNode::Bits.SwitchValueInst.HasDefault; + return SILInstruction::Bits.SwitchValueInst.HasDefault; } SILBasicBlock *getDefaultBB() const { assert(hasDefault() && "doesn't have a default"); @@ -8243,8 +8194,8 @@ class SwitchEnumInstBase : public BaseTy { Rest &&... rest) : BaseTy(Kind, DebugLoc, std::forward(rest)...), Operands(this, Operand) { - SILNode::Bits.SEIBase.HasDefault = bool(DefaultBB); - SILNode::Bits.SEIBase.NumCases = CaseBBs.size(); + SILInstruction::Bits.SEIBase.HasDefault = bool(DefaultBB); + SILInstruction::Bits.SEIBase.NumCases = CaseBBs.size(); // Initialize the case and successor arrays. auto *cases = getCaseBuf(); auto *succs = getSuccessorBuf(); @@ -8290,7 +8241,7 @@ class SwitchEnumInstBase : public BaseTy { static_cast(getNumCases() + hasDefault())}; } - unsigned getNumCases() const { return SILNode::Bits.SEIBase.NumCases; } + unsigned getNumCases() const { return SILInstruction::Bits.SEIBase.NumCases; } std::pair getCase(unsigned i) const { @@ -8390,7 +8341,7 @@ class SwitchEnumInstBase : public BaseTy { return eltDecl; } - bool hasDefault() const { return SILNode::Bits.SEIBase.HasDefault; } + bool hasDefault() const { return SILInstruction::Bits.SEIBase.HasDefault; } SILBasicBlock *getDefaultBB() const { assert(hasDefault() && "doesn't have a default"); @@ -8408,9 +8359,9 @@ class SwitchEnumInstBase : public BaseTy { return getSuccessorBuf()[getNumCases()].getCount(); } - static bool classof(SILNodePointer node) { - return node->getKind() >= SILNodeKind::SwitchEnumInst && - node->getKind() <= SILNodeKind::SwitchEnumAddrInst; + static bool classof(const SILInstruction *I) { + return I->getKind() >= SILInstructionKind::SwitchEnumInst && + I->getKind() <= SILInstructionKind::SwitchEnumAddrInst; } }; @@ -9162,8 +9113,8 @@ class OwnershipForwardingMultipleValueInstruction assert(classof(kind) && "Missing subclass from classof?!"); } - static bool classof(SILNodePointer node) { - if (auto *i = dyn_cast(node.get())) + static bool classof(const SILNode *n) { + if (auto *i = dyn_cast(n)) return classof(i); return false; } @@ -9190,8 +9141,8 @@ class DestructureStructResult final : public MultipleValueInstructionResult { : MultipleValueInstructionResult(ValueKind::DestructureStructResult, Index, Type, OwnershipKind) {} - static bool classof(SILNodePointer node) { - return node->getKind() == SILNodeKind::DestructureStructResult; + static bool classof(const SILNode *N) { + return N->getKind() == SILNodeKind::DestructureStructResult; } DestructureStructInst *getParent(); @@ -9219,8 +9170,8 @@ class DestructureStructInst final static DestructureStructInst *create(const SILFunction &F, SILDebugLocation Loc, SILValue Operand); - static bool classof(SILNodePointer node) { - return node->getKind() == SILNodeKind::DestructureStructInst; + static bool classof(const SILNode *N) { + return N->getKind() == SILNodeKind::DestructureStructInst; } }; @@ -9239,8 +9190,8 @@ class DestructureTupleResult final : public MultipleValueInstructionResult { : MultipleValueInstructionResult(ValueKind::DestructureTupleResult, Index, Type, OwnershipKind) {} - static bool classof(SILNodePointer node) { - return node->getKind() == SILNodeKind::DestructureTupleResult; + static bool classof(const SILNode *N) { + return N->getKind() == SILNodeKind::DestructureTupleResult; } DestructureTupleInst *getParent(); @@ -9268,8 +9219,8 @@ class DestructureTupleInst final static DestructureTupleInst *create(const SILFunction &F, SILDebugLocation Loc, SILValue Operand); - static bool classof(SILNodePointer node) { - return node->getKind() == SILNodeKind::DestructureTupleInst; + static bool classof(const SILNode *N) { + return N->getKind() == SILNodeKind::DestructureTupleInst; } }; diff --git a/include/swift/SIL/SILNode.h b/include/swift/SIL/SILNode.h index b9ffaf4c35444..5cab8b05686dc 100644 --- a/include/swift/SIL/SILNode.h +++ b/include/swift/SIL/SILNode.h @@ -18,6 +18,7 @@ #define SWIFT_SIL_SILNODE_H #include "llvm/Support/Compiler.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include "swift/Basic/InlineBitfield.h" #include "swift/Basic/LLVM.h" @@ -28,12 +29,9 @@ namespace swift { class SILBasicBlock; class SILFunction; class SILInstruction; -class SingleValueInstruction; -class NonSingleValueInstruction; class SILModule; +class SingleValueInstruction; class ValueBase; -class SILNode; -class SILValue; /// An enumeration which contains values for all the nodes in SILNodes.def. /// Other enumerators, like ValueKind and SILInstructionKind, ultimately @@ -52,26 +50,6 @@ enum { NumSILNodeKindBits = enum class SILInstructionKind : std::underlying_type::type; -/// A SILNode pointer which makes it possible to implicitly cast from all kind -/// of nodes, values and instructions (note: there is no implicit cast from -/// SILInstruction* to SILNode*). -/// It's mainly used to simplify classof-functions, but it can be used for other -/// SILNode-taking APIs, too. -/// Currently there is only a const-version of it. -class SILNodePointer { - const SILNode *node; -public: - SILNodePointer(const SILNode *node) : node(node) { } - SILNodePointer(const SILInstruction *inst); - SILNodePointer(const SingleValueInstruction *svi); - SILNodePointer(const NonSingleValueInstruction *nsvi); - SILNodePointer(SILValue value); - - const SILNode *get() const { return node; } - const SILNode *operator->() const { return node; } - operator const SILNode *() const { return node; } -}; - /// A SILNode is a node in the use-def graph of a SILFunction. It is /// either an instruction or a defined value which can be used by an /// instruction. A defined value may be an instruction result, a basic @@ -126,8 +104,10 @@ class alignas(8) SILNode { protected: union { uint64_t OpaqueBits; - SWIFT_INLINE_BITFIELD_BASE(SILNode, bitmax(NumSILNodeKindBits,8), - Kind : bitmax(NumSILNodeKindBits,8) + SWIFT_INLINE_BITFIELD_BASE(SILNode, bitmax(NumSILNodeKindBits,8)+1+1, + Kind : bitmax(NumSILNodeKindBits,8), + StorageLoc : 1, + IsRepresentativeNode : 1 ); SWIFT_INLINE_BITFIELD_EMPTY(ValueBase, SILNode); @@ -411,18 +391,71 @@ class alignas(8) SILNode { } Bits; + enum class SILNodeStorageLocation : uint8_t { Value, Instruction }; + + enum class IsRepresentative : bool { + No = false, + Yes = true, + }; + +private: + + SILNodeStorageLocation getStorageLoc() const { + return SILNodeStorageLocation(Bits.SILNode.StorageLoc); + } + + const SILNode *getRepresentativeSILNodeSlowPath() const; + protected: - SILNode(SILNodeKind kind) { + SILNode(SILNodeKind kind, SILNodeStorageLocation storageLoc, + IsRepresentative isRepresentative) { Bits.OpaqueBits = 0; Bits.SILNode.Kind = unsigned(kind); + Bits.SILNode.StorageLoc = unsigned(storageLoc); + Bits.SILNode.IsRepresentativeNode = unsigned(isRepresentative); } public: + /// Does the given kind of node inherit from multiple multiple SILNode base + /// classes? + /// + /// This enables one to know if their is a diamond in the inheritence + /// hierarchy for this SILNode. + static bool hasMultipleSILNodeBases(SILNodeKind kind) { + // Currently only SingleValueInstructions. Note that multi-result + // instructions shouldn't return true for this. + return kind >= SILNodeKind::First_SingleValueInstruction && + kind <= SILNodeKind::Last_SingleValueInstruction; + } + + /// Is this SILNode the representative SILNode subobject in this object? + bool isRepresentativeSILNodeInObject() const { + return Bits.SILNode.IsRepresentativeNode; + } + + /// Return a pointer to the representative SILNode subobject in this object. + SILNode *getRepresentativeSILNodeInObject() { + if (isRepresentativeSILNodeInObject()) + return this; + return const_cast(getRepresentativeSILNodeSlowPath()); + } + + const SILNode *getRepresentativeSILNodeInObject() const { + if (isRepresentativeSILNodeInObject()) + return this; + return getRepresentativeSILNodeSlowPath(); + } + LLVM_ATTRIBUTE_ALWAYS_INLINE SILNodeKind getKind() const { return SILNodeKind(Bits.SILNode.Kind); } + /// Return the SILNodeKind of this node's representative SILNode. + SILNodeKind getKindOfRepresentativeSILNodeInObject() const { + return getRepresentativeSILNodeInObject()->getKind(); + } + /// If this is a SILArgument or a SILInstruction get its parent basic block, /// otherwise return null. SILBasicBlock *getParentBlock() const; @@ -450,13 +483,14 @@ class alignas(8) SILNode { // Cast to SingleValueInstruction. This is an implementation detail // of the cast machinery. At a high level, all you need to know is to // never use static_cast to downcast a SILNode. - SILInstruction *castToInstruction(); - const SILInstruction *castToInstruction() const; - - static SILNode *instAsNode(SILInstruction *inst); - static const SILNode *instAsNode(const SILInstruction *inst); + SingleValueInstruction *castToSingleValueInstruction(); + const SingleValueInstruction *castToSingleValueInstruction() const { + return const_cast(this)->castToSingleValueInstruction(); + } - static bool classof(SILNodePointer node) { return true; } + static bool classof(const SILNode *node) { + return true; + } }; inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, @@ -465,46 +499,67 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, return OS; } -// Simply do a pointer cast from a SILNode to a SILNode. This is always -// possible, except the To-type is SILInstruction itself. -template -struct cast_from_SILNode { - static To *doit(SILNode *node) { return &static_cast(*node); } +template struct cast_sil_node_is_unambiguous { + // The only ambiguity right now is between the value and instruction + // nodes on a SingleValueInstruction. + static constexpr bool value = + // If the destination type isn't a subclass of ValueBase or + // SILInstruction, there's no ambiguity. + (!std::is_base_of::value && + !std::is_base_of::value) + + // If the destination type is a proper subclass of ValueBase + // that isn't a subclass of SILInstruction, there's no ambiguity. + || (std::is_base_of::value && + !std::is_same::value && + !std::is_base_of::value) + + // If the destination type is a proper subclass of SILInstruction + // that isn't a subclass of ValueBase, there's no ambiguity. + || (std::is_base_of::value && + !std::is_same::value && + !std::is_base_of::value); }; -// Handle the special case of casting a SILNode to SILInstruction itself. -// This does not apply to sub-classes of SILInstruction, because all sub-classes -// from SILInstructions are derived from SILNode. -template <> -struct cast_from_SILNode { - static SILInstruction *doit(SILNode *node) { - return &static_cast(*node->castToInstruction()); - } -}; -template <> -struct cast_from_SILNode { - static const SILInstruction *doit(SILNode *node) { - return &static_cast(*node->castToInstruction()); +template ::value, + bool IsKnownUnambiguous = + cast_sil_node_is_unambiguous::value> +struct cast_sil_node; + +// If all complete objects of the destination type are known to only +// contain a single node, we can just use a static_cast. +template +struct cast_sil_node { + static To *doit(SILNode *node) { + return &static_cast(*node); } }; -template ::value> -struct cast_from_SILInstruction; - -// Simply do a pointer cast from a SILInstruction to a SILInstruction. +// If we're casting to a subclass of SingleValueInstruction, we don't +// need to dynamically check whether the node is an SVI. In fact, +// we can't, because the static_cast will be ambiguous. template -struct cast_from_SILInstruction { - static To *doit(SILInstruction *inst) { - return &static_cast(*inst); +struct cast_sil_node { + static To *doit(SILNode *node) { + auto svi = node->castToSingleValueInstruction(); + return &static_cast(*svi); } }; -// Cast from a SILInstruction to a SILNode, which is not a SILInstruction. +// Otherwise, we need to dynamically check which case we're in. template -struct cast_from_SILInstruction { - static To *doit(SILInstruction *inst) { - return &static_cast(*SILNode::instAsNode(inst)); +struct cast_sil_node { + static To *doit(SILNode *node) { + // If the node isn't dynamically a SingleValueInstruction, then this + // is indeed the SILNode subobject that's statically observable in To. + if (!SILNode::hasMultipleSILNodeBases(node->getKind())) { + return &static_cast(*node); + } + + auto svi = node->castToSingleValueInstruction(); + return &static_cast(*svi); } }; @@ -512,36 +567,20 @@ struct cast_from_SILInstruction { namespace llvm { -/// Completely take over cast<>'ing from SILNode* and SILInstruction*. -/// A static_cast to ValueBase* or SILInstruction* can be quite wrong. +/// Completely take over cast<>'ing from SILNode*. A static_cast to +/// ValueBase* or SILInstruction* can be quite wrong. template struct cast_convert_val { using ret_type = typename cast_retty::ret_type; static ret_type doit(swift::SILNode *node) { - return swift::cast_from_SILNode::doit(node); + return swift::cast_sil_node::doit(node); } }; template struct cast_convert_val { using ret_type = typename cast_retty::ret_type; static ret_type doit(const swift::SILNode *node) { - return swift::cast_from_SILNode::doit(const_cast(node)); - } -}; -template -struct cast_convert_val { - using ret_type = typename cast_retty::ret_type; - static ret_type doit(swift::SILInstruction *inst) { - return swift::cast_from_SILInstruction::doit(inst); - } -}; -template -struct cast_convert_val { - using ret_type = typename cast_retty::ret_type; - static ret_type doit(const swift::SILInstruction *inst) { - return swift::cast_from_SILInstruction:: - doit(const_cast(inst)); + return swift::cast_sil_node::doit(const_cast(node)); } }; diff --git a/include/swift/SIL/SILNodes.def b/include/swift/SIL/SILNodes.def index ff4ef0104a27a..b88fbc85890b5 100644 --- a/include/swift/SIL/SILNodes.def +++ b/include/swift/SIL/SILNodes.def @@ -913,7 +913,6 @@ MULTIPLE_VALUE_INST(DestructureStructInst, destructure_struct, MULTIPLE_VALUE_INST(DestructureTupleInst, destructure_tuple, MultipleValueInstruction, None, DoesNotRelease) INST_RANGE(MultipleValueInstruction, BeginApplyInst, DestructureTupleInst) -NODE_RANGE(NonSingleValueInstruction, UnreachableInst, DestructureTupleInst) NODE_RANGE(SILInstruction, AllocStackInst, DestructureTupleInst) NODE_RANGE(SILNode, SILPhiArgument, DestructureTupleInst) diff --git a/include/swift/SIL/SILPrintContext.h b/include/swift/SIL/SILPrintContext.h index 39a0e9683abd4..0b9c2c1448b44 100644 --- a/include/swift/SIL/SILPrintContext.h +++ b/include/swift/SIL/SILPrintContext.h @@ -108,7 +108,7 @@ class SILPrintContext { SILPrintContext::ID getID(const SILBasicBlock *Block); - SILPrintContext::ID getID(SILNodePointer node); + SILPrintContext::ID getID(const SILNode *node); /// Returns true if the \p Scope has and ID assigned. bool hasScopeID(const SILDebugScope *Scope) const { diff --git a/include/swift/SIL/SILUndef.h b/include/swift/SIL/SILUndef.h index ecbf54df084aa..8d7540bc70a35 100644 --- a/include/swift/SIL/SILUndef.h +++ b/include/swift/SIL/SILUndef.h @@ -43,7 +43,7 @@ class SILUndef : public ValueBase { static bool classof(const SILArgument *) = delete; static bool classof(const SILInstruction *) = delete; - static bool classof(SILNodePointer node) { + static bool classof(const SILNode *node) { return node->getKind() == SILNodeKind::SILUndef; } }; diff --git a/include/swift/SIL/SILValue.h b/include/swift/SIL/SILValue.h index fbb289692a0a2..11bfa317eb984 100644 --- a/include/swift/SIL/SILValue.h +++ b/include/swift/SIL/SILValue.h @@ -346,8 +346,10 @@ class ValueBase : public SILNode, public SILAllocated { ValueBase &operator=(const ValueBase &) = delete; protected: - ValueBase(ValueKind kind, SILType type) - : SILNode(SILNodeKind(kind)), Type(type) {} + ValueBase(ValueKind kind, SILType type, IsRepresentative isRepresentative) + : SILNode(SILNodeKind(kind), SILNodeStorageLocation::Value, + isRepresentative), + Type(type) {} public: ~ValueBase() { @@ -515,9 +517,9 @@ class ValueBase : public SILNode, public SILAllocated { /// result index, or None if it is not defined by an instruction. Optional getDefiningInstructionResult(); - static bool classof(SILNodePointer node) { - return node->getKind() >= SILNodeKind::First_ValueBase && - node->getKind() <= SILNodeKind::Last_ValueBase; + static bool classof(const SILNode *N) { + return N->getKind() >= SILNodeKind::First_ValueBase && + N->getKind() <= SILNodeKind::Last_ValueBase; } static bool classof(const ValueBase *V) { return true; } @@ -616,8 +618,6 @@ class SILValue { void verifyOwnership(DeadEndBlocks *DEBlocks) const; }; -inline SILNodePointer::SILNodePointer(SILValue value) : node(value) { } - inline bool ValueOwnershipKind::isCompatibleWith(SILValue other) const { return isCompatibleWith(other.getOwnershipKind()); } diff --git a/include/swift/SILOptimizer/Analysis/AliasAnalysis.h b/include/swift/SILOptimizer/Analysis/AliasAnalysis.h index ac59ec026d00c..c33bca6b73dd1 100644 --- a/include/swift/SILOptimizer/Analysis/AliasAnalysis.h +++ b/include/swift/SILOptimizer/Analysis/AliasAnalysis.h @@ -153,7 +153,7 @@ class AliasAnalysis : public SILAnalysis { /// It's needed if e.g. \p inst is an address projection and its operand gets /// replaced with a different underlying object. void invalidateInstruction(SILInstruction *inst) { - handleDeleteNotification(inst->asSILNode()); + handleDeleteNotification(inst); } /// Perform an alias query to see if V1, V2 refer to the same values. diff --git a/include/swift/SILOptimizer/Utils/InstOptUtils.h b/include/swift/SILOptimizer/Utils/InstOptUtils.h index 04d44e6f2de22..fadacc4fd6883 100644 --- a/include/swift/SILOptimizer/Utils/InstOptUtils.h +++ b/include/swift/SILOptimizer/Utils/InstOptUtils.h @@ -260,6 +260,8 @@ getConcreteValueOfExistentialBox(AllocExistentialBoxInst *existentialBox, SILValue getConcreteValueOfExistentialBoxAddr(SILValue addr, SILInstruction *ignoreUser); +FullApplySite findApplyFromDevirtualizedResult(SILValue value); + /// Cast a value into the expected, ABI compatible type if necessary. /// This may happen e.g. when: /// - a type of the return value is a subclass of the expected return type. diff --git a/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h b/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h index 8eac3bf971620..eab73575a5e1f 100644 --- a/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h +++ b/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h @@ -269,7 +269,7 @@ class LSValue : public LSBase { } auto Res = Path.getValue().createExtract(Val, &*InsertPt, true); if (Val != Base) { - Res = makeCopiedValueAvailable(Res, Inst->getParent(), + Res = makeCopiedValueAvailable(Res, Inst->getParentBlock(), jointPostDomComputer); Builder.emitEndBorrowOperation(InsertPt->getLoc(), Val); // Insert a destroy on the Base diff --git a/include/swift/SILOptimizer/Utils/SCCVisitor.h b/include/swift/SILOptimizer/Utils/SCCVisitor.h index 2bc658529e355..e5f2dd665b201 100644 --- a/include/swift/SILOptimizer/Utils/SCCVisitor.h +++ b/include/swift/SILOptimizer/Utils/SCCVisitor.h @@ -84,6 +84,8 @@ class SCCVisitor { } DFSInfo &addDFSInfo(SILNode *node) { + assert(node->isRepresentativeSILNodeInObject()); + auto insertion = ValueInfoMap.try_emplace(node, new DFSInfo(node, CurrentNum++)); assert(insertion.second && "Cannot add DFS info more than once!"); @@ -91,6 +93,7 @@ class SCCVisitor { } DFSInfo &getDFSInfo(SILNode *node) { + assert(node->isRepresentativeSILNodeInObject()); auto it = ValueInfoMap.find(node); assert(it != ValueInfoMap.end() && "Expected to find value in DFS info map!"); @@ -167,7 +170,7 @@ class SCCVisitor { } void maybeDFS(SILInstruction *inst) { - (void) maybeDFSCanonicalNode(inst->asSILNode()); + (void) maybeDFSCanonicalNode(inst->getRepresentativeSILNodeInObject()); } /// Continue a DFS from the given node, finding the strongly @@ -175,6 +178,9 @@ class SCCVisitor { /// and returning the DFSInfo for the node. /// But if we've already visited the node, just return null. DFSInfo *maybeDFSCanonicalNode(SILNode *node) { + assert(node->isRepresentativeSILNodeInObject() && + "should already be canonical"); + if (!Visited.insert(node).second) return nullptr; @@ -188,7 +194,7 @@ class SCCVisitor { // Visit each unvisited operand, updating the lowest DFS number we've seen // reachable in User's SCC. for (SILValue operandValue : operands) { - SILNode *operandNode = operandValue; + SILNode *operandNode = operandValue->getRepresentativeSILNodeInObject(); if (auto operandNodeInfo = maybeDFSCanonicalNode(operandNode)) { nodeInfo.LowNum = std::min(nodeInfo.LowNum, operandNodeInfo->LowNum); } else if (DFSStack.count(operandNode)) { diff --git a/lib/SIL/IR/SILArgument.cpp b/lib/SIL/IR/SILArgument.cpp index 693f8820868cb..1e9e87eaed7d6 100644 --- a/lib/SIL/IR/SILArgument.cpp +++ b/lib/SIL/IR/SILArgument.cpp @@ -27,7 +27,7 @@ SILArgument::SILArgument(ValueKind subClassKind, SILBasicBlock *inputParentBlock, SILType type, ValueOwnershipKind ownershipKind, const ValueDecl *inputDecl) - : ValueBase(subClassKind, type), + : ValueBase(subClassKind, type, IsRepresentative::Yes), parentBlock(inputParentBlock), decl(inputDecl) { Bits.SILArgument.VOKind = static_cast(ownershipKind); inputParentBlock->insertArgument(inputParentBlock->args_end(), this); diff --git a/lib/SIL/IR/SILBasicBlock.cpp b/lib/SIL/IR/SILBasicBlock.cpp index 7d49b03436067..58a9c8614eec3 100644 --- a/lib/SIL/IR/SILBasicBlock.cpp +++ b/lib/SIL/IR/SILBasicBlock.cpp @@ -115,7 +115,7 @@ void SILBasicBlock::eraseInstructions() { SILBasicBlock::iterator SILBasicBlock::erase(SILInstruction *I) { // Notify the delete handlers that this instruction is going away. SILModule &module = getModule(); - module.notifyDeleteHandlers(I->asSILNode()); + module.notifyDeleteHandlers(&*I); auto nextIter = InstList.erase(I); module.deallocateInst(I); return nextIter; diff --git a/lib/SIL/IR/SILFunction.cpp b/lib/SIL/IR/SILFunction.cpp index 6e216ebacb3a0..3704620a071b7 100644 --- a/lib/SIL/IR/SILFunction.cpp +++ b/lib/SIL/IR/SILFunction.cpp @@ -246,10 +246,10 @@ void SILFunction::numberValues(llvm::DenseMap & for (auto &I : BB) { auto results = I.getResults(); if (results.empty()) { - ValueToNumberMap[I.asSILNode()] = idx++; + ValueToNumberMap[&I] = idx++; } else { // Assign the instruction node the first result ID. - ValueToNumberMap[I.asSILNode()] = idx; + ValueToNumberMap[&I] = idx; for (auto result : results) { ValueToNumberMap[result] = idx++; } diff --git a/lib/SIL/IR/SILInstruction.cpp b/lib/SIL/IR/SILInstruction.cpp index 88a49bbf57582..d9bdd427dc031 100644 --- a/lib/SIL/IR/SILInstruction.cpp +++ b/lib/SIL/IR/SILInstruction.cpp @@ -99,10 +99,13 @@ transferNodesFromList(llvm::ilist_traits &L2, // Assert that all subclasses of ValueBase implement classof. #define NODE(CLASS, PARENT) \ - ASSERT_IMPLEMENTS_STATIC(CLASS, PARENT, classof, bool(SILNodePointer)); + ASSERT_IMPLEMENTS_STATIC(CLASS, PARENT, classof, bool(const SILNode*)); #include "swift/SIL/SILNodes.def" -SILFunction *SILInstruction::getFunction() const { +SILFunction *SILInstruction::getFunction() { + return getParent()->getParent(); +} +const SILFunction *SILInstruction::getFunction() const { return getParent()->getParent(); } @@ -1537,7 +1540,7 @@ MultipleValueInstruction::getIndexOfResult(SILValue Target) const { MultipleValueInstructionResult::MultipleValueInstructionResult( ValueKind valueKind, unsigned index, SILType type, ValueOwnershipKind ownershipKind) - : ValueBase(valueKind, type) { + : ValueBase(valueKind, type, IsRepresentative::No) { setOwnershipKind(ownershipKind); setIndex(index); } diff --git a/lib/SIL/IR/SILInstructions.cpp b/lib/SIL/IR/SILInstructions.cpp index 4b6e8510db812..76e754947fd75 100644 --- a/lib/SIL/IR/SILInstructions.cpp +++ b/lib/SIL/IR/SILInstructions.cpp @@ -154,11 +154,11 @@ AllocStackInst::AllocStackInst(SILDebugLocation Loc, SILType elementType, bool hasDynamicLifetime) : InstructionBase(Loc, elementType.getAddressType()), dynamicLifetime(hasDynamicLifetime) { - SILNode::Bits.AllocStackInst.NumOperands = + SILInstruction::Bits.AllocStackInst.NumOperands = TypeDependentOperands.size(); - assert(SILNode::Bits.AllocStackInst.NumOperands == + assert(SILInstruction::Bits.AllocStackInst.NumOperands == TypeDependentOperands.size() && "Truncation"); - SILNode::Bits.AllocStackInst.VarInfo = + SILInstruction::Bits.AllocStackInst.VarInfo = TailAllocatedDebugVariable(Var, getTrailingObjects()).getRawValue(); TrailingOperandsList::InitOperandsList(getAllOperands().begin(), this, TypeDependentOperands); @@ -205,10 +205,10 @@ AllocRefInstBase::AllocRefInstBase(SILInstructionKind Kind, bool objc, bool canBeOnStack, ArrayRef ElementTypes) : AllocationInst(Kind, Loc, ObjectType) { - SILNode::Bits.AllocRefInstBase.ObjC = objc; - SILNode::Bits.AllocRefInstBase.OnStack = canBeOnStack; - SILNode::Bits.AllocRefInstBase.NumTailTypes = ElementTypes.size(); - assert(SILNode::Bits.AllocRefInstBase.NumTailTypes == + SILInstruction::Bits.AllocRefInstBase.ObjC = objc; + SILInstruction::Bits.AllocRefInstBase.OnStack = canBeOnStack; + SILInstruction::Bits.AllocRefInstBase.NumTailTypes = ElementTypes.size(); + assert(SILInstruction::Bits.AllocRefInstBase.NumTailTypes == ElementTypes.size() && "Truncation"); assert(!objc || ElementTypes.empty()); } @@ -892,7 +892,7 @@ static void *allocateLiteralInstWithBitSize(SILModule &M, unsigned bits) { IntegerLiteralInst::IntegerLiteralInst(SILDebugLocation Loc, SILType Ty, const llvm::APInt &Value) : InstructionBase(Loc, Ty) { - SILNode::Bits.IntegerLiteralInst.numBits = Value.getBitWidth(); + SILInstruction::Bits.IntegerLiteralInst.numBits = Value.getBitWidth(); std::uninitialized_copy_n(Value.getRawData(), Value.getNumWords(), getTrailingObjects()); } @@ -952,7 +952,7 @@ IntegerLiteralInst *IntegerLiteralInst::create(IntegerLiteralExpr *E, /// getValue - Return the APInt for the underlying integer literal. APInt IntegerLiteralInst::getValue() const { - auto numBits = SILNode::Bits.IntegerLiteralInst.numBits; + auto numBits = SILInstruction::Bits.IntegerLiteralInst.numBits; return APInt(numBits, {getTrailingObjects(), getWordsForBitWidth(numBits)}); } @@ -960,7 +960,7 @@ APInt IntegerLiteralInst::getValue() const { FloatLiteralInst::FloatLiteralInst(SILDebugLocation Loc, SILType Ty, const APInt &Bits) : InstructionBase(Loc, Ty) { - SILNode::Bits.FloatLiteralInst.numBits = Bits.getBitWidth(); + SILInstruction::Bits.FloatLiteralInst.numBits = Bits.getBitWidth(); std::uninitialized_copy_n(Bits.getRawData(), Bits.getNumWords(), getTrailingObjects()); } @@ -992,7 +992,7 @@ FloatLiteralInst *FloatLiteralInst::create(FloatLiteralExpr *E, } APInt FloatLiteralInst::getBits() const { - auto numBits = SILNode::Bits.FloatLiteralInst.numBits; + auto numBits = SILInstruction::Bits.FloatLiteralInst.numBits; return APInt(numBits, {getTrailingObjects(), getWordsForBitWidth(numBits)}); } @@ -1005,8 +1005,8 @@ APFloat FloatLiteralInst::getValue() const { StringLiteralInst::StringLiteralInst(SILDebugLocation Loc, StringRef Text, Encoding encoding, SILType Ty) : InstructionBase(Loc, Ty) { - SILNode::Bits.StringLiteralInst.TheEncoding = unsigned(encoding); - SILNode::Bits.StringLiteralInst.Length = Text.size(); + SILInstruction::Bits.StringLiteralInst.TheEncoding = unsigned(encoding); + SILInstruction::Bits.StringLiteralInst.Length = Text.size(); memcpy(getTrailingObjects(), Text.data(), Text.size()); } @@ -1036,14 +1036,14 @@ CondFailInst *CondFailInst::create(SILDebugLocation DebugLoc, SILValue Operand, } uint64_t StringLiteralInst::getCodeUnitCount() { - return SILNode::Bits.StringLiteralInst.Length; + return SILInstruction::Bits.StringLiteralInst.Length; } StoreInst::StoreInst( SILDebugLocation Loc, SILValue Src, SILValue Dest, StoreOwnershipQualifier Qualifier = StoreOwnershipQualifier::Unqualified) : InstructionBase(Loc), Operands(this, Src, Dest) { - SILNode::Bits.StoreInst.OwnershipQualifier = unsigned(Qualifier); + SILInstruction::Bits.StoreInst.OwnershipQualifier = unsigned(Qualifier); } StoreBorrowInst::StoreBorrowInst(SILDebugLocation DebugLoc, SILValue Src, @@ -1074,7 +1074,7 @@ StringRef swift::getSILAccessEnforcementName(SILAccessEnforcement enforcement) { AssignInst::AssignInst(SILDebugLocation Loc, SILValue Src, SILValue Dest, AssignOwnershipQualifier Qualifier) : AssignInstBase(Loc, Src, Dest) { - SILNode::Bits.AssignInst.OwnershipQualifier = unsigned(Qualifier); + SILInstruction::Bits.AssignInst.OwnershipQualifier = unsigned(Qualifier); } AssignByWrapperInst::AssignByWrapperInst(SILDebugLocation Loc, @@ -1084,7 +1084,7 @@ AssignByWrapperInst::AssignByWrapperInst(SILDebugLocation Loc, AssignOwnershipQualifier Qualifier) : AssignInstBase(Loc, Src, Dest, Initializer, Setter) { assert(Initializer->getType().is()); - SILNode::Bits.AssignByWrapperInst.OwnershipQualifier = + SILInstruction::Bits.AssignByWrapperInst.OwnershipQualifier = unsigned(Qualifier); } @@ -1100,8 +1100,8 @@ CopyAddrInst::CopyAddrInst(SILDebugLocation Loc, SILValue SrcLValue, SILValue DestLValue, IsTake_t isTakeOfSrc, IsInitialization_t isInitializationOfDest) : InstructionBase(Loc), Operands(this, SrcLValue, DestLValue) { - SILNode::Bits.CopyAddrInst.IsTakeOfSrc = bool(isTakeOfSrc); - SILNode::Bits.CopyAddrInst.IsInitializationOfDest = + SILInstruction::Bits.CopyAddrInst.IsTakeOfSrc = bool(isTakeOfSrc); + SILInstruction::Bits.CopyAddrInst.IsInitializationOfDest = bool(isInitializationOfDest); } @@ -1561,8 +1561,8 @@ CondBranchInst::CondBranchInst(SILDebugLocation Loc, SILValue Condition, : InstructionBaseWithTrailingOperands(Condition, Args, Loc), DestBBs{{{this, TrueBB, TrueBBCount}, {this, FalseBB, FalseBBCount}}} { assert(Args.size() == (NumTrue + NumFalse) && "Invalid number of args"); - SILNode::Bits.CondBranchInst.NumTrueArgs = NumTrue; - assert(SILNode::Bits.CondBranchInst.NumTrueArgs == NumTrue && + SILInstruction::Bits.CondBranchInst.NumTrueArgs = NumTrue; + assert(SILInstruction::Bits.CondBranchInst.NumTrueArgs == NumTrue && "Truncation"); assert(TrueBB != FalseBB && "Identical destinations"); } @@ -1646,7 +1646,7 @@ void CondBranchInst::swapSuccessors() { // Finally swap the number of arguments that we have. The number of false // arguments is derived from the number of true arguments, therefore: - SILNode::Bits.CondBranchInst.NumTrueArgs = getNumFalseArgs(); + SILInstruction::Bits.CondBranchInst.NumTrueArgs = getNumFalseArgs(); } SwitchValueInst::SwitchValueInst(SILDebugLocation Loc, SILValue Operand, @@ -1654,7 +1654,7 @@ SwitchValueInst::SwitchValueInst(SILDebugLocation Loc, SILValue Operand, ArrayRef Cases, ArrayRef BBs) : InstructionBaseWithTrailingOperands(Operand, Cases, Loc) { - SILNode::Bits.SwitchValueInst.HasDefault = bool(DefaultBB); + SILInstruction::Bits.SwitchValueInst.HasDefault = bool(DefaultBB); // Initialize the successor array. auto *succs = getSuccessorBuf(); unsigned OperandBitWidth = 0; diff --git a/lib/SIL/IR/SILPrinter.cpp b/lib/SIL/IR/SILPrinter.cpp index f735c5e2bdd6c..c60e5f98cccbd 100644 --- a/lib/SIL/IR/SILPrinter.cpp +++ b/lib/SIL/IR/SILPrinter.cpp @@ -761,18 +761,17 @@ class SILPrinter : public SILInstructionVisitor { /// Print out the users of the SILValue \p V. Return true if we printed out /// either an id or a use list. Return false otherwise. - bool printUsersOfValue(SILValue value, bool printedSlashes) { - return printUserList({value}, value, printedSlashes); - } - - bool printUsersOfInstruction(const SILInstruction *inst, bool printedSlashes) { + bool printUsersOfSILNode(const SILNode *node, bool printedSlashes) { llvm::SmallVector values; - llvm::copy(inst->getResults(), std::back_inserter(values)); - return printUserList(values, inst, printedSlashes); - } + if (auto *value = dyn_cast(node)) { + values.push_back(value); + } else if (auto *inst = dyn_cast(node)) { + assert(!isa(inst) && "SingleValueInstruction was " + "handled by the previous " + "value base check."); + llvm::copy(inst->getResults(), std::back_inserter(values)); + } - bool printUserList(ArrayRef values, SILNodePointer node, - bool printedSlashes) { // If the set of values is empty, we need to print the ID of // the instruction. Otherwise, if none of the values has a use, // we don't need to do anything. @@ -1012,7 +1011,7 @@ class SILPrinter : public SILInstructionVisitor { printedSlashes = printTypeDependentOperands(I); // Print users, or id for valueless instructions. - printedSlashes = printUsersOfInstruction(I, printedSlashes); + printedSlashes = printUsersOfSILNode(I, printedSlashes); // Print SIL location. if (Ctx.printVerbose()) { @@ -1057,7 +1056,7 @@ class SILPrinter : public SILInstructionVisitor { << Ctx.getID(arg->getParent()) << " : " << arg->getType(); // Print users. - (void) printUsersOfValue(arg, false); + (void) printUsersOfSILNode(arg, false); *this << '\n'; } @@ -1094,13 +1093,13 @@ class SILPrinter : public SILInstructionVisitor { visit(static_cast(nonConstParent)); // Print users. - (void)printUsersOfValue(result, false); + (void)printUsersOfSILNode(result, false); *this << '\n'; } void printInContext(const SILNode *node) { - auto sortByID = [&](SILNodePointer a, SILNodePointer b) { + auto sortByID = [&](const SILNode *a, const SILNode *b) { return Ctx.getID(a).Number < Ctx.getID(b).Number; }; @@ -3129,7 +3128,7 @@ void SILInstruction::dumpInContext() const { } void SILInstruction::printInContext(llvm::raw_ostream &OS) const { SILPrintContext Ctx(OS); - SILPrinter(Ctx).printInContext(asSILNode()); + SILPrinter(Ctx).printInContext(this); } void SILVTableEntry::print(llvm::raw_ostream &OS) const { @@ -3593,11 +3592,11 @@ ID SILPrintContext::getID(const SILBasicBlock *Block) { return R; } -ID SILPrintContext::getID(SILNodePointer node) { +ID SILPrintContext::getID(const SILNode *node) { if (node == nullptr) return {ID::Null, ~0U}; - if (isa(node.get())) + if (isa(node)) return {ID::SILUndef, 0}; SILBasicBlock *BB = node->getParentBlock(); @@ -3626,7 +3625,7 @@ ID SILPrintContext::getID(SILNodePointer node) { unsigned idx = 0; for (auto &I : *BB) { // Give the instruction itself the next ID. - ValueToIDMap[I.asSILNode()] = idx; + ValueToIDMap[&I] = idx; // If there are no results, make sure we don't reuse that ID. auto results = I.getResults(); diff --git a/lib/SIL/IR/SILUndef.cpp b/lib/SIL/IR/SILUndef.cpp index e1c94d0216353..21831a8cf6683 100644 --- a/lib/SIL/IR/SILUndef.cpp +++ b/lib/SIL/IR/SILUndef.cpp @@ -16,7 +16,7 @@ using namespace swift; SILUndef::SILUndef(SILType type) - : ValueBase(ValueKind::SILUndef, type) {} + : ValueBase(ValueKind::SILUndef, type, IsRepresentative::Yes) {} SILUndef *SILUndef::get(SILType ty, SILModule &m) { SILUndef *&entry = m.UndefValues[ty]; diff --git a/lib/SIL/IR/SILValue.cpp b/lib/SIL/IR/SILValue.cpp index bd4488ea840fb..46e8247b99e1b 100644 --- a/lib/SIL/IR/SILValue.cpp +++ b/lib/SIL/IR/SILValue.cpp @@ -99,28 +99,52 @@ ValueBase::getDefiningInstructionResult() { } SILBasicBlock *SILNode::getParentBlock() const { - if (auto *Inst = dyn_cast(this)) + auto *CanonicalNode = + const_cast(this)->getRepresentativeSILNodeInObject(); + if (auto *Inst = dyn_cast(CanonicalNode)) return Inst->getParent(); - if (auto *Arg = dyn_cast(this)) + if (auto *Arg = dyn_cast(CanonicalNode)) return Arg->getParent(); - if (auto *MVR = dyn_cast(this)) { - return MVR->getParent()->getParent(); - } return nullptr; } SILFunction *SILNode::getFunction() const { - if (auto *parentBlock = getParentBlock()) - return parentBlock->getParent(); + auto *CanonicalNode = + const_cast(this)->getRepresentativeSILNodeInObject(); + if (auto *Inst = dyn_cast(CanonicalNode)) + return Inst->getFunction(); + if (auto *Arg = dyn_cast(CanonicalNode)) + return Arg->getFunction(); return nullptr; } SILModule *SILNode::getModule() const { - if (SILFunction *func = getFunction()) - return &func->getModule(); + auto *CanonicalNode = + const_cast(this)->getRepresentativeSILNodeInObject(); + if (auto *Inst = dyn_cast(CanonicalNode)) + return &Inst->getModule(); + if (auto *Arg = dyn_cast(CanonicalNode)) + return &Arg->getModule(); return nullptr; } +const SILNode *SILNode::getRepresentativeSILNodeSlowPath() const { + assert(getStorageLoc() != SILNodeStorageLocation::Instruction); + + if (isa(this)) { + assert(hasMultipleSILNodeBases(getKind())); + return &static_cast( + static_cast( + static_cast(*this))); + } + + if (auto *MVR = dyn_cast(this)) { + return MVR->getParent(); + } + + llvm_unreachable("Invalid value for slow path"); +} + /// Get a location for this value. SILLocation SILValue::getLoc() const { if (auto *instr = Value->getDefiningInstruction()) diff --git a/lib/SIL/Utils/OwnershipUtils.cpp b/lib/SIL/Utils/OwnershipUtils.cpp index 70845d2eda8b6..d18b47bdd3345 100644 --- a/lib/SIL/Utils/OwnershipUtils.cpp +++ b/lib/SIL/Utils/OwnershipUtils.cpp @@ -26,29 +26,31 @@ bool swift::isValueAddressOrTrivial(SILValue v) { } // These operations forward both owned and guaranteed ownership. -static bool isOwnershipForwardingInstructionKind(SILInstructionKind kind) { +// +// FIXME: Should be implemented as a SILInstruction type check-cast. +static bool isOwnershipForwardingValueKind(SILNodeKind kind) { switch (kind) { - case SILInstructionKind::TupleInst: - case SILInstructionKind::StructInst: - case SILInstructionKind::EnumInst: - case SILInstructionKind::DifferentiableFunctionInst: - case SILInstructionKind::LinearFunctionInst: - case SILInstructionKind::OpenExistentialRefInst: - case SILInstructionKind::UpcastInst: - case SILInstructionKind::UncheckedValueCastInst: - case SILInstructionKind::UncheckedRefCastInst: - case SILInstructionKind::ConvertFunctionInst: - case SILInstructionKind::RefToBridgeObjectInst: - case SILInstructionKind::BridgeObjectToRefInst: - case SILInstructionKind::UnconditionalCheckedCastInst: - case SILInstructionKind::UncheckedEnumDataInst: - case SILInstructionKind::SelectEnumInst: - case SILInstructionKind::SwitchEnumInst: - case SILInstructionKind::CheckedCastBranchInst: - case SILInstructionKind::DestructureStructInst: - case SILInstructionKind::DestructureTupleInst: - case SILInstructionKind::MarkDependenceInst: - case SILInstructionKind::InitExistentialRefInst: + case SILNodeKind::TupleInst: + case SILNodeKind::StructInst: + case SILNodeKind::EnumInst: + case SILNodeKind::DifferentiableFunctionInst: + case SILNodeKind::LinearFunctionInst: + case SILNodeKind::OpenExistentialRefInst: + case SILNodeKind::UpcastInst: + case SILNodeKind::UncheckedValueCastInst: + case SILNodeKind::UncheckedRefCastInst: + case SILNodeKind::ConvertFunctionInst: + case SILNodeKind::RefToBridgeObjectInst: + case SILNodeKind::BridgeObjectToRefInst: + case SILNodeKind::UnconditionalCheckedCastInst: + case SILNodeKind::UncheckedEnumDataInst: + case SILNodeKind::SelectEnumInst: + case SILNodeKind::SwitchEnumInst: + case SILNodeKind::CheckedCastBranchInst: + case SILNodeKind::DestructureStructInst: + case SILNodeKind::DestructureTupleInst: + case SILNodeKind::MarkDependenceInst: + case SILNodeKind::InitExistentialRefInst: return true; default: return false; @@ -57,17 +59,17 @@ static bool isOwnershipForwardingInstructionKind(SILInstructionKind kind) { // These operations forward guaranteed ownership, but don't necessarily forward // owned values. -static bool isGuaranteedForwardingInstructionKind(SILInstructionKind kind) { +static bool isGuaranteedForwardingValueKind(SILNodeKind kind) { switch (kind) { - case SILInstructionKind::TupleExtractInst: - case SILInstructionKind::StructExtractInst: - case SILInstructionKind::DifferentiableFunctionExtractInst: - case SILInstructionKind::LinearFunctionExtractInst: - case SILInstructionKind::OpenExistentialValueInst: - case SILInstructionKind::OpenExistentialBoxValueInst: + case SILNodeKind::TupleExtractInst: + case SILNodeKind::StructExtractInst: + case SILNodeKind::DifferentiableFunctionExtractInst: + case SILNodeKind::LinearFunctionExtractInst: + case SILNodeKind::OpenExistentialValueInst: + case SILNodeKind::OpenExistentialBoxValueInst: return true; default: - return isOwnershipForwardingInstructionKind(kind); + return isOwnershipForwardingValueKind(kind); } } @@ -81,21 +83,19 @@ bool swift::canOpcodeForwardGuaranteedValues(SILValue value) { return true; } - auto *inst = value->getDefiningInstruction(); - if (!inst) - return false; - - bool result = isGuaranteedForwardingInstructionKind(inst->getKind()); + auto *node = value->getRepresentativeSILNodeInObject(); + bool result = isGuaranteedForwardingValueKind(node->getKind()); if (result) { - assert(!isa(inst)); - assert(OwnershipForwardingMixin::isa(inst)); + assert(!isa(node)); + assert(OwnershipForwardingMixin::isa(node)); } return result; } bool swift::canOpcodeForwardGuaranteedValues(Operand *use) { auto *user = use->getUser(); - bool result = isOwnershipForwardingInstructionKind(user->getKind()); + auto kind = user->getKind(); + bool result = isOwnershipForwardingValueKind(SILNodeKind(kind)); if (result) { assert(!isa(user)); assert(OwnershipForwardingMixin::isa(user)); @@ -103,12 +103,12 @@ bool swift::canOpcodeForwardGuaranteedValues(Operand *use) { return result; } -static bool isOwnedForwardingValueKind(SILInstructionKind kind) { +static bool isOwnedForwardingValueKind(SILNodeKind kind) { switch (kind) { - case SILInstructionKind::MarkUninitializedInst: + case SILNodeKind::MarkUninitializedInst: return true; default: - return isOwnershipForwardingInstructionKind(kind); + return isOwnershipForwardingValueKind(kind); } } @@ -121,21 +121,19 @@ bool swift::canOpcodeForwardOwnedValues(SILValue value) { assert(OwnershipForwardingMixin::isa(predTerm)); return true; } - auto *inst = value->getDefiningInstruction(); - if (!inst) - return false; - - bool result = isOwnedForwardingValueKind(inst->getKind()); + auto *node = value->getRepresentativeSILNodeInObject(); + bool result = isOwnedForwardingValueKind(node->getKind()); if (result) { - assert(!isa(inst)); - assert(OwnershipForwardingMixin::isa(inst)); + assert(!isa(node)); + assert(OwnershipForwardingMixin::isa(node)); } return result; } bool swift::canOpcodeForwardOwnedValues(Operand *use) { auto *user = use->getUser(); - bool result = isOwnershipForwardingInstructionKind(user->getKind()); + auto kind = SILNodeKind(user->getKind()); + bool result = isOwnershipForwardingValueKind(kind); if (result) { assert(OwnershipForwardingMixin::isa(user)); } diff --git a/lib/SILOptimizer/ARC/ARCRegionState.cpp b/lib/SILOptimizer/ARC/ARCRegionState.cpp index 2161cc569fb72..f30d0049ff500 100644 --- a/lib/SILOptimizer/ARC/ARCRegionState.cpp +++ b/lib/SILOptimizer/ARC/ARCRegionState.cpp @@ -194,7 +194,7 @@ bool ARCRegionState::processBlockBottomUp( LLVM_DEBUG(llvm::dbgs() << "VISITING:\n " << *I); - auto Result = DataflowVisitor.visit(I->asSILNode()); + auto Result = DataflowVisitor.visit(I); // If this instruction can have no further effects on another instructions, // continue. This happens for instance if we have cleared all of the state @@ -359,7 +359,7 @@ bool ARCRegionState::processBlockTopDown( LLVM_DEBUG(llvm::dbgs() << "VISITING:\n " << *I); - auto Result = DataflowVisitor.visit(I->asSILNode()); + auto Result = DataflowVisitor.visit(I); // If this instruction can have no further effects on another instructions, // continue. This happens for instance if we have cleared all of the state diff --git a/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp b/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp index c462faa2f05c6..1e851075f9719 100644 --- a/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp +++ b/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp @@ -87,7 +87,7 @@ bool ARCSequenceDataflowEvaluator::processBBTopDown(ARCBBState &BBState) { LLVM_DEBUG(llvm::dbgs() << "VISITING:\n " << I); - auto Result = DataflowVisitor.visit(I.asSILNode()); + auto Result = DataflowVisitor.visit(&I); // If this instruction can have no further effects on another instructions, // continue. This happens for instance if we have cleared all of the state @@ -247,7 +247,7 @@ bool ARCSequenceDataflowEvaluator::processBBBottomUp( LLVM_DEBUG(llvm::dbgs() << "VISITING:\n " << I); - auto Result = DataflowVisitor.visit(I.asSILNode()); + auto Result = DataflowVisitor.visit(&I); // If this instruction can have no further effects on another instructions, // continue. This happens for instance if we have cleared all of the state diff --git a/lib/SILOptimizer/ARC/RCStateTransition.cpp b/lib/SILOptimizer/ARC/RCStateTransition.cpp index 2bf5947104331..07a4ff9634ad0 100644 --- a/lib/SILOptimizer/ARC/RCStateTransition.cpp +++ b/lib/SILOptimizer/ARC/RCStateTransition.cpp @@ -129,12 +129,12 @@ bool RCStateTransition::matchingInst(SILInstruction *Inst) const { return false; if (Kind == RCStateTransitionKind::StrongIncrement) { - auto InstTransKind = getRCStateTransitionKind(Inst->asSILNode()); + auto InstTransKind = getRCStateTransitionKind(Inst); return InstTransKind == RCStateTransitionKind::StrongDecrement; } if (Kind == RCStateTransitionKind::StrongDecrement) { - auto InstTransKind = getRCStateTransitionKind(Inst->asSILNode()); + auto InstTransKind = getRCStateTransitionKind(Inst); return InstTransKind == RCStateTransitionKind::StrongIncrement; } diff --git a/lib/SILOptimizer/ARC/RCStateTransition.h b/lib/SILOptimizer/ARC/RCStateTransition.h index d7fc602d2775d..7789cb9697f77 100644 --- a/lib/SILOptimizer/ARC/RCStateTransition.h +++ b/lib/SILOptimizer/ARC/RCStateTransition.h @@ -87,9 +87,9 @@ class RCStateTransition { RCStateTransition(ImmutablePointerSet *I) { assert(I->size() == 1); SILInstruction *Inst = *I->begin(); - Kind = getRCStateTransitionKind(Inst->asSILNode()); + Kind = getRCStateTransitionKind(Inst); if (isRCStateTransitionEndPoint(Kind)) { - EndPoint = Inst->asSILNode(); + EndPoint = Inst; return; } diff --git a/lib/SILOptimizer/ARC/RefCountState.cpp b/lib/SILOptimizer/ARC/RefCountState.cpp index a03ac87819f6e..6b2e7495cc6c7 100644 --- a/lib/SILOptimizer/ARC/RefCountState.cpp +++ b/lib/SILOptimizer/ARC/RefCountState.cpp @@ -363,7 +363,7 @@ bool BottomUpRefCountState::handlePotentialGuaranteedUser( // Instructions that we do not recognize (and thus will not move) and that // *must* use RCIdentity, implies we are always known safe as long as meet // over all path constraints are satisfied. - if (isRCStateTransitionUnknown(PotentialGuaranteedUser->asSILNode())) + if (isRCStateTransitionUnknown(PotentialGuaranteedUser)) if (mustUseValue(PotentialGuaranteedUser, getRCRoot(), AA)) FoundNonARCUser = true; @@ -422,7 +422,7 @@ bool BottomUpRefCountState::handlePotentialUser(SILInstruction *PotentialUser, // Instructions that we do not recognize (and thus will not move) and that // *must* use RCIdentity, implies we are always known safe as long as meet // over all path constraints are satisfied. - if (isRCStateTransitionUnknown(PotentialUser->asSILNode())) + if (isRCStateTransitionUnknown(PotentialUser)) if (mustUseValue(PotentialUser, getRCRoot(), AA)) FoundNonARCUser = true; diff --git a/lib/SILOptimizer/Analysis/AliasAnalysis.cpp b/lib/SILOptimizer/Analysis/AliasAnalysis.cpp index 94ebca5098e26..b9e74eb7a6234 100644 --- a/lib/SILOptimizer/Analysis/AliasAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/AliasAnalysis.cpp @@ -539,6 +539,8 @@ bool AliasAnalysis::typesMayAlias(SILType T1, SILType T2, } void AliasAnalysis::handleDeleteNotification(SILNode *node) { + assert(node->isRepresentativeSILNodeInObject()); + // The pointer 'node' is going away. We can't scan the whole cache // and remove all of the occurrences of the pointer. Instead we remove // the pointer from the index caches. diff --git a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp index e34cd443addcd..1f36e4d6156fa 100644 --- a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp @@ -207,20 +207,20 @@ SILValue EscapeAnalysis::getPointerRoot(SILValue value) { return value; } -static bool isNonWritableMemoryAddress(SILValue V) { +static bool isNonWritableMemoryAddress(SILNode *V) { switch (V->getKind()) { - case ValueKind::FunctionRefInst: - case ValueKind::DynamicFunctionRefInst: - case ValueKind::PreviousDynamicFunctionRefInst: - case ValueKind::WitnessMethodInst: - case ValueKind::ClassMethodInst: - case ValueKind::SuperMethodInst: - case ValueKind::ObjCMethodInst: - case ValueKind::ObjCSuperMethodInst: - case ValueKind::StringLiteralInst: - case ValueKind::ThinToThickFunctionInst: - case ValueKind::ThinFunctionToPointerInst: - case ValueKind::PointerToThinFunctionInst: + case SILNodeKind::FunctionRefInst: + case SILNodeKind::DynamicFunctionRefInst: + case SILNodeKind::PreviousDynamicFunctionRefInst: + case SILNodeKind::WitnessMethodInst: + case SILNodeKind::ClassMethodInst: + case SILNodeKind::SuperMethodInst: + case SILNodeKind::ObjCMethodInst: + case SILNodeKind::ObjCSuperMethodInst: + case SILNodeKind::StringLiteralInst: + case SILNodeKind::ThinToThickFunctionInst: + case SILNodeKind::ThinFunctionToPointerInst: + case SILNodeKind::PointerToThinFunctionInst: // These instructions return pointers to memory which can't be a // destination of a store. return true; @@ -1553,8 +1553,8 @@ void EscapeAnalysis::ConnectionGraph::print(llvm::raw_ostream &OS) const { const char *Separator = ""; for (unsigned VIdx = Nd->UsePoints.find_first(); VIdx != -1u; VIdx = Nd->UsePoints.find_next(VIdx)) { - SILInstruction *inst = UsePointTable[VIdx]; - OS << Separator << '%' << InstToIDMap[inst->asSILNode()]; + auto node = UsePointTable[VIdx]; + OS << Separator << '%' << InstToIDMap[node]; Separator = ","; } break; @@ -1622,10 +1622,8 @@ void EscapeAnalysis::ConnectionGraph::verify() const { ReachableBlocks reachable(F); reachable.visit([this](SILBasicBlock *bb) { for (auto &i : *bb) { - if (auto *svi = dyn_cast(&i)) { - if (isNonWritableMemoryAddress(svi)) - continue; - } + if (isNonWritableMemoryAddress(&i)) + continue; if (auto ai = dyn_cast(&i)) { if (EA->canOptimizeArrayUninitializedCall(ai).isValid()) @@ -2062,17 +2060,17 @@ void EscapeAnalysis::analyzeInstruction(SILInstruction *I, if (auto *SVI = dyn_cast(I)) { if (getPointerBase(SVI)) return; - - // Instructions which return the address of non-writable memory cannot have - // an effect on escaping. - if (isNonWritableMemoryAddress(SVI)) - return; } // Incidental uses produce no values and have no effect on their operands. if (isIncidentalUse(I)) return; + // Instructions which return the address of non-writable memory cannot have + // an effect on escaping. + if (isNonWritableMemoryAddress(I)) + return; + switch (I->getKind()) { case SILInstructionKind::AllocStackInst: case SILInstructionKind::AllocRefInst: diff --git a/lib/SILOptimizer/Analysis/IVAnalysis.cpp b/lib/SILOptimizer/Analysis/IVAnalysis.cpp index d26fe04615821..a2e2e0903a732 100644 --- a/lib/SILOptimizer/Analysis/IVAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/IVAnalysis.cpp @@ -20,8 +20,9 @@ using namespace swift::PatternMatch; #if !defined(NDEBUG) static bool inSCC(ValueBase *value, IVInfo::SCCType &SCC) { + SILNode *valueNode = value->getRepresentativeSILNodeInObject(); for (SILNode *node : SCC) { - if (node == value) + if (node->getRepresentativeSILNodeInObject() == valueNode) return true; } return false; diff --git a/lib/SILOptimizer/Mandatory/DiagnoseInfiniteRecursion.cpp b/lib/SILOptimizer/Mandatory/DiagnoseInfiniteRecursion.cpp index 3a6f7ad4b8d38..17cb413096987 100644 --- a/lib/SILOptimizer/Mandatory/DiagnoseInfiniteRecursion.cpp +++ b/lib/SILOptimizer/Mandatory/DiagnoseInfiniteRecursion.cpp @@ -158,13 +158,15 @@ class Invariants { /// Recursively walks the use-def chain starting at \p value and returns /// true if all visited values are invariant. bool isInvariantValue(SILValue value, - SmallPtrSetImpl &visited) const { - if (SILInstruction *inst = value->getDefiningInstruction()) { - // Avoid exponential complexity in case a value is used by multiple - // operands. - if (!visited.insert(inst).second) - return true; + SmallPtrSetImpl &visited) const { + SILNode *node = value->getRepresentativeSILNodeInObject(); + // Avoid exponential complexity in case a value is used by multiple + // operands. + if (!visited.insert(node).second) + return true; + + if (auto *inst = dyn_cast(node)) { if (!isMemoryInvariant() && inst->mayReadFromMemory()) return false; @@ -226,7 +228,7 @@ class Invariants { case TermKind::SwitchEnumInst: case TermKind::CheckedCastBranchInst: case TermKind::CheckedCastValueBranchInst: { - SmallPtrSet visited; + SmallPtrSet visited; return isInvariantValue(term->getOperand(0), visited); } default: diff --git a/lib/SILOptimizer/Mandatory/Differentiation.cpp b/lib/SILOptimizer/Mandatory/Differentiation.cpp index faa104b4d77e0..d8cbc32302db7 100644 --- a/lib/SILOptimizer/Mandatory/Differentiation.cpp +++ b/lib/SILOptimizer/Mandatory/Differentiation.cpp @@ -1292,7 +1292,7 @@ void DifferentiationTransformer::foldDifferentiableFunctionExtraction( bool DifferentiationTransformer::processDifferentiableFunctionInst( DifferentiableFunctionInst *dfi) { PrettyStackTraceSILNode dfiTrace("canonicalizing `differentiable_function`", - dfi); + cast(dfi)); PrettyStackTraceSILFunction fnTrace("...in", dfi->getFunction()); LLVM_DEBUG({ auto &s = getADDebugStream() << "Processing DifferentiableFunctionInst:\n"; @@ -1332,7 +1332,8 @@ bool DifferentiationTransformer::processDifferentiableFunctionInst( bool DifferentiationTransformer::processLinearFunctionInst( LinearFunctionInst *lfi) { - PrettyStackTraceSILNode dfiTrace("canonicalizing `linear_function`", lfi); + PrettyStackTraceSILNode dfiTrace("canonicalizing `linear_function`", + cast(lfi)); PrettyStackTraceSILFunction fnTrace("...in", lfi->getFunction()); LLVM_DEBUG({ auto &s = getADDebugStream() << "Processing LinearFunctionInst:\n"; diff --git a/lib/SILOptimizer/PassManager/PassManager.cpp b/lib/SILOptimizer/PassManager/PassManager.cpp index d9908a07706c2..d08990304f95b 100644 --- a/lib/SILOptimizer/PassManager/PassManager.cpp +++ b/lib/SILOptimizer/PassManager/PassManager.cpp @@ -1034,7 +1034,7 @@ namespace llvm { std::string Label; raw_string_ostream O(Label); SILInstruction *Inst = I.baseIter->FAS.getInstruction(); - O << '%' << Node->CG->InstToIDMap[Inst->asSILNode()]; + O << '%' << Node->CG->InstToIDMap[Inst]; return Label; } diff --git a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp index 20faada9c142e..331a42e1ab01c 100644 --- a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp +++ b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp @@ -188,8 +188,7 @@ class DCE : public SILFunctionTransform { void computeMinPredecessorLevels(PostDomTreeNode *root); void insertControllingInfo(SILBasicBlock *Block, unsigned Level); - void markValueLive(SILValue V); - void markInstructionLive(SILInstruction *Inst); + void markValueLive(SILNode *V); void markTerminatorArgsLive(SILBasicBlock *Pred, SILBasicBlock *Succ, size_t ArgIndex); void markControllingTerminatorsLive(SILBasicBlock *Block); @@ -209,28 +208,30 @@ class DCE : public SILFunctionTransform { // Keep track of the fact that V is live and add it to our worklist // so that we can process the values it depends on. -void DCE::markValueLive(SILValue V) { - if (SILInstruction *inst = V->getDefiningInstruction()) - return markInstructionLive(inst); - - if (!LiveValues.insert(V).second || isa(V)) +void DCE::markValueLive(SILNode *V) { + V = V->getRepresentativeSILNodeInObject(); + if (LiveValues.count(V) || isa(V)) return; - LLVM_DEBUG(llvm::dbgs() << "Marking as live: " << *V); + LLVM_DEBUG(llvm::dbgs() << "Marking as live:\n"); + LLVM_DEBUG(V->dump()); - auto *Arg = cast(V); - markControllingTerminatorsLive(Arg->getParent()); - propagateLiveBlockArgument(Arg); -} + LiveValues.insert(V); -void DCE::markInstructionLive(SILInstruction *Inst) { - if (!LiveValues.insert(Inst->asSILNode()).second) + if (auto *Def = dyn_cast(V)) { + markControllingTerminatorsLive(Def->getParent()); + Worklist.push_back(Def); return; + } + + // TODO: MultiValueInstruction - LLVM_DEBUG(llvm::dbgs() << "Marking as live: " << *Inst); + assert(isa(V) && + "Only expected instructions and arguments!"); - markControllingTerminatorsLive(Inst->getParent()); - Worklist.push_back(Inst); + auto *Arg = cast(V); + markControllingTerminatorsLive(Arg->getParent()); + propagateLiveBlockArgument(Arg); } /// Gets the producing instruction of a cond_fail condition. Currently these @@ -262,7 +263,7 @@ void DCE::markLive(SILFunction &F) { if (auto *Prod = getProducer(cast(&I))) { addReverseDependency(Prod, &I); } else { - markInstructionLive(&I); + markValueLive(&I); } break; } @@ -271,7 +272,7 @@ void DCE::markLive(SILFunction &F) { if (!Op->getType().isAddress()) { addReverseDependency(Op, &I); } else { - markInstructionLive(&I); + markValueLive(&I); } break; } @@ -289,7 +290,7 @@ void DCE::markLive(SILFunction &F) { } default: if (seemsUseful(&I)) - markInstructionLive(&I); + markValueLive(&I); } } } @@ -318,7 +319,7 @@ void DCE::markTerminatorArgsLive(SILBasicBlock *Pred, // If the arguments are live, we need to keep the terminator that // delivers those arguments. - markInstructionLive(Term); + markValueLive(Term); switch (Term->getTermKind()) { case TermKind::ReturnInst: @@ -379,11 +380,11 @@ void DCE::propagateLiveBlockArgument(SILArgument *Arg) { // is in reverse direction: Only if its definition (the Arg) is alive, also // the debug_value instruction is alive. for (Operand *DU : getDebugUses(Arg)) - markInstructionLive(DU->getUser()); + markValueLive(DU->getUser()); // Mark all reverse dependencies on the Arg live for (auto *depInst : ReverseDependencies.lookup(Arg)) { - markInstructionLive(depInst); + markValueLive(depInst); } auto *Block = Arg->getParent(); @@ -405,14 +406,14 @@ void DCE::propagateLiveness(SILInstruction *I) { // debug_value instruction is alive. for (auto result : I->getResults()) for (Operand *DU : getDebugUses(result)) - markInstructionLive(DU->getUser()); + markValueLive(DU->getUser()); // Handle all other reverse-dependency instructions, like cond_fail, // fix_lifetime, destroy_value, etc. Only if the definition is alive, the // user itself is alive. for (auto res : I->getResults()) { for (auto *depInst : ReverseDependencies.lookup(res)) { - markInstructionLive(depInst); + markValueLive(depInst); } } return; @@ -492,7 +493,7 @@ void DCE::replaceBranchWithJump(SILInstruction *Inst, SILBasicBlock *Block) { } void DCE::endLifetimeOfLiveValue(SILValue value, SILInstruction *insertPt) { - if (!LiveValues.count(value)) { + if (!LiveValues.count(value->getRepresentativeSILNodeInObject())) { return; } SILBuilderWithScope builder(insertPt); @@ -539,7 +540,7 @@ bool DCE::removeDead(SILFunction &F) { auto insertPt = getInsertAfterPoint(arg).getValue(); SILBuilderWithScope builder(insertPt); auto *destroy = builder.createDestroyValue(insertPt->getLoc(), arg); - LiveValues.insert(destroy->asSILNode()); + LiveValues.insert(destroy->getRepresentativeSILNodeInObject()); } i++; Changed = true; @@ -564,7 +565,7 @@ bool DCE::removeDead(SILFunction &F) { for (auto I = BB.begin(), E = BB.end(); I != E; ) { auto *Inst = &*I; ++I; - if (LiveValues.count(Inst->asSILNode()) || isa(Inst)) + if (LiveValues.count(Inst) || isa(Inst)) continue; // We want to replace dead terminators with unconditional branches to @@ -800,7 +801,7 @@ void DCE::markControllingTerminatorsLive(SILBasicBlock *Block) { collectControllingBlocks(Block, ControllingBlocks); for (auto BB : ControllingBlocks) - markInstructionLive(BB->getTerminator()); + markValueLive(BB->getTerminator()); } } // end anonymous namespace diff --git a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp index 90fe9cbdb6ba2..3c1d0269a0aaa 100644 --- a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp +++ b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp @@ -662,7 +662,7 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *ASI) { } // Remove dead address instructions that may be uses of the allocation. - SILNode *Node = Inst->asSILNode(); + SILNode *Node = Inst; while (isa(Node) || isa(Node) || isa(Node)) { diff --git a/lib/SILOptimizer/Utils/ConstExpr.cpp b/lib/SILOptimizer/Utils/ConstExpr.cpp index c5ba918ea011d..d0d29dd2adbbd 100644 --- a/lib/SILOptimizer/Utils/ConstExpr.cpp +++ b/lib/SILOptimizer/Utils/ConstExpr.cpp @@ -793,7 +793,7 @@ ConstExprFunctionState::computeOpaqueCallResult(ApplyInst *apply, SILFunction *callee) { LLVM_DEBUG(llvm::dbgs() << "ConstExpr Opaque Callee: " << *callee << "\n"); return evaluator.getUnknown( - apply, + (SILInstruction *)apply, UnknownReason::createCalleeImplementationUnknown(callee)); } @@ -882,7 +882,7 @@ ConstExprFunctionState::computeWellKnownCallResult(ApplyInst *apply, } } return evaluator.getUnknown( - apply, + (SILInstruction *)apply, UnknownReason::createTrap(message, evaluator.getAllocator())); } case WellKnownFunction::ArrayInitEmpty: { // Array.init() @@ -893,7 +893,7 @@ ConstExprFunctionState::computeWellKnownCallResult(ApplyInst *apply, auto typeValue = getConstantValue(apply->getOperand(1)); if (typeValue.getKind() != SymbolicValue::Metatype) { return typeValue.isConstant() - ? getUnknown(evaluator, apply, + ? getUnknown(evaluator, (SILInstruction *)apply, UnknownReason::InvalidOperandValue) : typeValue; } @@ -928,7 +928,8 @@ ConstExprFunctionState::computeWellKnownCallResult(ApplyInst *apply, // Allocating uninitialized arrays is supported only in flow-sensitive mode. // TODO: the top-level mode in the interpreter should be phased out. if (recursivelyComputeValueIfNotInState) - return getUnknown(evaluator, apply, UnknownReason::Default); + return getUnknown(evaluator, (SILInstruction *)apply, + UnknownReason::Default); SmallVector elementConstants; // Set array elements to uninitialized state. Subsequent stores through @@ -1002,7 +1003,8 @@ ConstExprFunctionState::computeWellKnownCallResult(ApplyInst *apply, if (!arrayValue.isConstant()) return arrayValue; if (arrayValue.getKind() != SymbolicValue::Array) { - return getUnknown(evaluator, apply, UnknownReason::InvalidOperandValue); + return getUnknown(evaluator, (SILInstruction *)apply, + UnknownReason::InvalidOperandValue); } // Create a new array storage by appending the \c element to the existing @@ -1040,14 +1042,16 @@ ConstExprFunctionState::computeWellKnownCallResult(ApplyInst *apply, conventions.getNumParameters() == 4 && "unexpected signature"); auto literal = getConstantValue(apply->getOperand(1)); if (literal.getKind() != SymbolicValue::String) { - return getUnknown(evaluator, apply, UnknownReason::InvalidOperandValue); + return getUnknown(evaluator, (SILInstruction *)apply, + UnknownReason::InvalidOperandValue); } auto literalVal = literal.getStringValue(); auto byteCount = getConstantValue(apply->getOperand(2)); if (byteCount.getKind() != SymbolicValue::Integer || byteCount.getIntegerValue().getLimitedValue() != literalVal.size()) { - return getUnknown(evaluator, apply, UnknownReason::InvalidOperandValue); + return getUnknown(evaluator, (SILInstruction *)apply, + UnknownReason::InvalidOperandValue); } setValue(apply, literal); return None; @@ -1064,7 +1068,8 @@ ConstExprFunctionState::computeWellKnownCallResult(ApplyInst *apply, return otherString; } if (otherString.getKind() != SymbolicValue::String) { - return getUnknown(evaluator, apply, UnknownReason::InvalidOperandValue); + return getUnknown(evaluator, (SILInstruction *)apply, + UnknownReason::InvalidOperandValue); } auto inoutOperand = apply->getOperand(2); @@ -1073,7 +1078,8 @@ ConstExprFunctionState::computeWellKnownCallResult(ApplyInst *apply, return firstString; } if (firstString.getKind() != SymbolicValue::String) { - return getUnknown(evaluator, apply, UnknownReason::InvalidOperandValue); + return getUnknown(evaluator, (SILInstruction *)apply, + UnknownReason::InvalidOperandValue); } auto result = SmallString<8>(firstString.getStringValue()); @@ -1091,12 +1097,14 @@ ConstExprFunctionState::computeWellKnownCallResult(ApplyInst *apply, auto firstString = getConstantValue(apply->getOperand(1)); if (firstString.getKind() != SymbolicValue::String) { - return getUnknown(evaluator, apply, UnknownReason::InvalidOperandValue); + return getUnknown(evaluator, (SILInstruction *)apply, + UnknownReason::InvalidOperandValue); } auto otherString = getConstantValue(apply->getOperand(2)); if (otherString.getKind() != SymbolicValue::String) { - return getUnknown(evaluator, apply, UnknownReason::InvalidOperandValue); + return getUnknown(evaluator, (SILInstruction *)apply, + UnknownReason::InvalidOperandValue); } // The result is a Swift.Bool which is a struct that wraps an Int1. @@ -1122,7 +1130,8 @@ ConstExprFunctionState::computeWellKnownCallResult(ApplyInst *apply, } if (stringArgument.getKind() != SymbolicValue::String) { - return getUnknown(evaluator, apply, UnknownReason::InvalidOperandValue); + return getUnknown(evaluator, (SILInstruction *)apply, + UnknownReason::InvalidOperandValue); } // Replace all precent symbol (%) in the string with double percents (%%) @@ -1154,7 +1163,8 @@ ConstExprFunctionState::computeWellKnownCallResult(ApplyInst *apply, Optional isSignedIntegerType = getSignIfStdlibIntegerType(argumentType); if (!isSignedIntegerType.hasValue()) { - return getUnknown(evaluator, apply, UnknownReason::InvalidOperandValue); + return getUnknown(evaluator, (SILInstruction *)apply, + UnknownReason::InvalidOperandValue); } // Load the stdlib integer's value and convert it to a string. SymbolicValue stdlibIntegerValue = @@ -1203,7 +1213,8 @@ ConstExprFunctionState::computeCallResult(ApplyInst *apply) { // Determine the callee. auto calleeFn = getConstantValue(apply->getOperand(0)); if (calleeFn.getKind() != SymbolicValue::Function) - return getUnknown(evaluator, apply, UnknownReason::InvalidOperandValue); + return getUnknown(evaluator, (SILInstruction *)apply, + UnknownReason::InvalidOperandValue); SILFunction *callee = calleeFn.getFunctionValue(); evaluator.recordCalledFunctionIfEnabled(callee); @@ -1220,7 +1231,7 @@ ConstExprFunctionState::computeCallResult(ApplyInst *apply) { auto op = apply->getOperand(i + 1); SymbolicValue argValue = getConstantValue(op); if (!argValue.isConstant()) { - return evaluator.getUnknown(apply, + return evaluator.getUnknown((SILInstruction *)apply, UnknownReason::createCallArgumentUnknown(i)); } paramConstants.push_back(argValue); @@ -1269,7 +1280,7 @@ ConstExprFunctionState::computeCallResult(ApplyInst *apply) { auto conf = protoSelfToConcreteType.lookupConformance( protocol->getSelfInterfaceType()->getCanonicalType(), protocol); if (conf.isInvalid()) - return getUnknown(evaluator, apply, + return getUnknown(evaluator, (SILInstruction *)apply, UnknownReason::UnknownWitnessMethodConformance); callSubMap = getWitnessMethodSubstitutions( @@ -1698,7 +1709,7 @@ llvm::Optional ConstExprFunctionState::evaluateClosureCreation( if (!calleeValue.isConstant()) return calleeValue; if (calleeValue.getKind() != SymbolicValue::Function) { - return getUnknown(evaluator, closureInst, + return getUnknown(evaluator, (SILInstruction *)closureInst, UnknownReason::InvalidOperandValue); } @@ -1785,7 +1796,7 @@ ConstExprFunctionState::evaluateFlowSensitive(SILInstruction *inst) { return None; // Conditional fail actually failed. return evaluator.getUnknown( - inst->asSILNode(), + (SILInstruction *)inst, UnknownReason::createTrap( (Twine("trap: ") + condFail->getMessage()).str(), evaluator.getAllocator())); @@ -1855,8 +1866,7 @@ ConstExprFunctionState::evaluateFlowSensitive(SILInstruction *inst) { LLVM_DEBUG(llvm::dbgs() << "ConstExpr Unknown FS: " << *inst << "\n"); // If this is an unknown instruction with no results then bail out. - return getUnknown(evaluator, inst->asSILNode(), - UnknownReason::UnsupportedInstruction); + return getUnknown(evaluator, inst, UnknownReason::UnsupportedInstruction); } std::pair, Optional> @@ -1975,8 +1985,8 @@ ConstExprFunctionState::evaluateInstructionAndGetNext( DynamicCastFeasibility castResult = classifyDynamicCast( inst->getModule().getSwiftModule(), sourceType, targetType); if (castResult == DynamicCastFeasibility::MaySucceed) { - return {None, getUnknown(evaluator, inst->asSILNode(), - UnknownReason::UnknownCastResult)}; + return {None, + getUnknown(evaluator, inst, UnknownReason::UnknownCastResult)}; } // Determine the basic block to jump to. SILBasicBlock *resultBB = @@ -1997,8 +2007,8 @@ ConstExprFunctionState::evaluateInstructionAndGetNext( LLVM_DEBUG(llvm::dbgs() << "ConstExpr: Unknown Branch Instruction: " << *inst << "\n"); - return {None, getUnknown(evaluator, inst->asSILNode(), - UnknownReason::UnsupportedInstruction)}; + return {None, + getUnknown(evaluator, inst, UnknownReason::UnsupportedInstruction)}; } /// Evaluate a call to the specified function as if it were a constant @@ -2044,8 +2054,7 @@ evaluateAndCacheCall(SILFunction &fn, SubstitutionMap substitutionMap, // Make sure we haven't exceeded our interpreter iteration cap. if (++numInstEvaluated > ConstExprLimit) { - return getUnknown(evaluator, inst->asSILNode(), - UnknownReason::TooManyInstructions); + return getUnknown(evaluator, inst, UnknownReason::TooManyInstructions); } if (isa(inst)) { @@ -2196,7 +2205,7 @@ ConstExprStepEvaluator::skipByMakingEffectsNonConstant( SmallVector accessPath; auto *memoryObject = constVal.getAddressValue(accessPath); auto unknownValue = SymbolicValue::getUnknown( - inst->asSILNode(), + inst, UnknownReason::create(UnknownReason::MutatedByUnevaluatedInstruction), {}, evaluator.getAllocator()); @@ -2213,7 +2222,7 @@ ConstExprStepEvaluator::skipByMakingEffectsNonConstant( for (auto result : inst->getResults()) { internalState->setValue( result, SymbolicValue::getUnknown( - inst->asSILNode(), + inst, UnknownReason::create( UnknownReason::ReturnedByUnevaluatedInstruction), {}, evaluator.getAllocator())); diff --git a/lib/SILOptimizer/Utils/InstOptUtils.cpp b/lib/SILOptimizer/Utils/InstOptUtils.cpp index 63a66567a8574..0db1c49fe2892 100644 --- a/lib/SILOptimizer/Utils/InstOptUtils.cpp +++ b/lib/SILOptimizer/Utils/InstOptUtils.cpp @@ -810,6 +810,20 @@ getConcreteValueOfExistentialBoxAddr(SILValue addr, SILInstruction *ignoreUser) return getConcreteValueOfExistentialBox(box, singleStackStore); } +// Devirtualization of functions with covariant return types produces +// a result that is not an apply, but takes an apply as an +// argument. Attempt to dig the apply out from this result. +FullApplySite swift::findApplyFromDevirtualizedResult(SILValue v) { + if (auto Apply = FullApplySite::isa(v)) + return Apply; + + if (isa(v) || isa(v) || isa(v)) + return findApplyFromDevirtualizedResult( + cast(v)->getOperand(0)); + + return FullApplySite(); +} + bool swift::mayBindDynamicSelf(SILFunction *F) { if (!F->hasDynamicSelfMetadata()) return false; diff --git a/lib/SILOptimizer/Utils/LoadStoreOptUtils.cpp b/lib/SILOptimizer/Utils/LoadStoreOptUtils.cpp index dd96084f69954..e319d0bf6d0ec 100644 --- a/lib/SILOptimizer/Utils/LoadStoreOptUtils.cpp +++ b/lib/SILOptimizer/Utils/LoadStoreOptUtils.cpp @@ -120,7 +120,7 @@ void LSValue::reduceInner(LSLocation &Base, SILModule *M, Builder, RegularLocation::getAutoGeneratedLocation(), Base.getType(M, context).getObjectType(), Vals); - auto AvailVal = makeNewValueAvailable(AI.get(), InsertPt->getParent(), + auto AvailVal = makeNewValueAvailable(AI.get(), InsertPt->getParentBlock(), jointPostDomComputer); // This is the Value for the current base.