blob: c726693200620b2861991c32036112a519ebb11e [file] [log] [blame]
//===--- 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<SILInstruction *, 1>;
InnerTy User;
public:
BranchPropagatedUser(SILInstruction *I) : User(I) {
assert(!isa<CondBranchInst>(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<CondBranchInst>(getInst());
unsigned Number = getCondBranchSuccessorID();
if (Number == CondBranchInst::TrueIdx)
return CBI->getTrueBB();
return CBI->getFalseBB();
}
bool isCondBranchUser() const {
return isa<CondBranchInst>(User.getPointer());
}
unsigned getCondBranchSuccessorID() const {
assert(isCondBranchUser());
return User.getInt();
}
SILBasicBlock::iterator getIterator() const {
return User.getPointer()->getIterator();
}
void *getAsOpaqueValue() const {
return llvm::PointerLikeTypeTraits<InnerTy>::getAsVoidPointer(User);
}
static BranchPropagatedUser getFromOpaqueValue(void *p) {
InnerTy TmpUser =
llvm::PointerLikeTypeTraits<InnerTy>::getFromVoidPointer(p);
if (auto *CBI = dyn_cast<CondBranchInst>(TmpUser.getPointer())) {
return BranchPropagatedUser(CBI, TmpUser.getInt());
}
return BranchPropagatedUser(TmpUser.getPointer());
}
enum {
NumLowBitsAvailable =
llvm::PointerLikeTypeTraits<InnerTy>::NumLowBitsAvailable
};
};
} // namespace swift
namespace llvm {
template <> struct PointerLikeTypeTraits<swift::BranchPropagatedUser> {
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