//===--- BranchPropagatedUser.h -------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2018 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_SIL_BRANCHPROPAGATEDUSER_H #define SWIFT_SIL_BRANCHPROPAGATEDUSER_H #include "swift/SIL/SILBasicBlock.h" #include "swift/SIL/SILInstruction.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/PointerLikeTypeTraits.h" namespace swift { /// This is a class that models normal users and also cond_br users that are /// associated with the block in the target block. This is safe to do since in /// Semantic SIL, cond_br with non-trivial arguments are not allowed to have /// critical edges. In non-semantic SIL, it is expected that any user of /// BranchPropagatedUser and friends break all such critical edges. class BranchPropagatedUser { using InnerTy = llvm::PointerIntPair; InnerTy User; public: BranchPropagatedUser(SILInstruction *I) : User(I) { assert(!isa(I)); } BranchPropagatedUser(CondBranchInst *I) : User(I) {} BranchPropagatedUser(CondBranchInst *I, unsigned SuccessorIndex) : User(I, SuccessorIndex) { assert(SuccessorIndex == CondBranchInst::TrueIdx || SuccessorIndex == CondBranchInst::FalseIdx); } BranchPropagatedUser(const BranchPropagatedUser &Other) : User(Other.User) {} BranchPropagatedUser &operator=(const BranchPropagatedUser &Other) { User = Other.User; return *this; } operator SILInstruction *() { return User.getPointer(); } operator const SILInstruction *() const { return User.getPointer(); } SILInstruction *getInst() const { return User.getPointer(); } SILBasicBlock *getParent() const { if (!isCondBranchUser()) { return getInst()->getParent(); } auto *CBI = cast(getInst()); unsigned Number = getCondBranchSuccessorID(); if (Number == CondBranchInst::TrueIdx) return CBI->getTrueBB(); return CBI->getFalseBB(); } bool isCondBranchUser() const { return isa(User.getPointer()); } unsigned getCondBranchSuccessorID() const { assert(isCondBranchUser()); return User.getInt(); } SILBasicBlock::iterator getIterator() const { return User.getPointer()->getIterator(); } void *getAsOpaqueValue() const { return llvm::PointerLikeTypeTraits::getAsVoidPointer(User); } static BranchPropagatedUser getFromOpaqueValue(void *p) { InnerTy TmpUser = llvm::PointerLikeTypeTraits::getFromVoidPointer(p); if (auto *CBI = dyn_cast(TmpUser.getPointer())) { return BranchPropagatedUser(CBI, TmpUser.getInt()); } return BranchPropagatedUser(TmpUser.getPointer()); } enum { NumLowBitsAvailable = llvm::PointerLikeTypeTraits::NumLowBitsAvailable }; }; } // namespace swift namespace llvm { template <> struct PointerLikeTypeTraits { public: using BranchPropagatedUser = swift::BranchPropagatedUser; static void *getAsVoidPointer(BranchPropagatedUser v) { return v.getAsOpaqueValue(); } static BranchPropagatedUser getFromVoidPointer(void *p) { return BranchPropagatedUser::getFromOpaqueValue(p); } enum { NumLowBitsAvailable = BranchPropagatedUser::NumLowBitsAvailable }; }; } // namespace llvm #endif