//===--- OwnershipPhiOperand.h --------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #ifndef SWIFT_SILOPTIMIZER_SEMANTICARC_OWNERSHIPPHIOPERAND_H #define SWIFT_SILOPTIMIZER_SEMANTICARC_OWNERSHIPPHIOPERAND_H #include "swift/Basic/STLExtras.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILBasicBlock.h" #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILUndef.h" #include "swift/SIL/SILValue.h" namespace swift { namespace semanticarc { /// The operand of a "phi" in the induced ownership graph of a def-use graph. /// /// Some examples: br, struct, tuple. class LLVM_LIBRARY_VISIBILITY OwnershipPhiOperand { public: enum Kind { Branch, Struct, Tuple, }; private: Operand *op; OwnershipPhiOperand(Operand *op) : op(op) {} public: static std::optional get(const Operand *op) { switch (op->getUser()->getKind()) { case SILInstructionKind::BranchInst: case SILInstructionKind::StructInst: case SILInstructionKind::TupleInst: return {{const_cast(op)}}; default: return std::nullopt; } } Kind getKind() const { switch (op->getUser()->getKind()) { case SILInstructionKind::BranchInst: return Kind::Branch; case SILInstructionKind::StructInst: return Kind::Struct; case SILInstructionKind::TupleInst: return Kind::Tuple; default: llvm_unreachable("unhandled case?!"); } } operator const Operand *() const { return op; } operator Operand *() { return op; } Operand *getOperand() const { return op; } SILValue getValue() const { return op->get(); } SILType getType() const { return op->get()->getType(); } unsigned getOperandNumber() const { return op->getOperandNumber(); } void markUndef() & { op->set(SILUndef::get(getValue())); } SILInstruction *getInst() const { return op->getUser(); } /// Return true if this phi consumes a borrow. /// /// If so, we may need to insert an extra begin_borrow to balance the +1 when /// converting owned ownership phis to guaranteed ownership phis. bool isGuaranteedConsuming() const { switch (getKind()) { case Kind::Branch: return true; case Kind::Tuple: case Kind::Struct: return false; } llvm_unreachable("unhandled operand kind!"); } bool operator<(const OwnershipPhiOperand &other) const { return op < other.op; } bool operator==(const OwnershipPhiOperand &other) const { return op == other.op; } bool visitResults(function_ref visitor) const { switch (getKind()) { case Kind::Struct: return visitor(cast(getInst())); case Kind::Tuple: return visitor(cast(getInst())); case Kind::Branch: { auto *br = cast(getInst()); unsigned opNum = getOperandNumber(); return llvm::all_of( br->getSuccessorBlocks(), [&](SILBasicBlock *succBlock) { return visitor(succBlock->getSILPhiArguments()[opNum]); }); } } llvm_unreachable("unhandled operand kind!"); } }; } // namespace semanticarc } // namespace swift #endif // SWIFT_SILOPTIMIZER_SEMANTICARC_OWNERSHIPPHIOPERAND_H