forked from OSchip/llvm-project
[VPlan] Add VPUserID to distinguish between recipes and others.
This allows cast/dyn_cast'ing from VPUser to recipes. This is needed because there are VPUsers that are not recipes. Reviewed By: gilr, a.elovikov Differential Revision: https://reviews.llvm.org/D100257
This commit is contained in:
parent
dfd929d261
commit
cc1a6361d3
|
@ -188,56 +188,26 @@ VPBlockBase *VPBlockBase::getEnclosingBlockWithPredecessors() {
|
|||
return Parent->getEnclosingBlockWithPredecessors();
|
||||
}
|
||||
|
||||
static VPValue *getSingleOperandOrNull(VPUser &U) {
|
||||
if (U.getNumOperands() == 1)
|
||||
return U.getOperand(0);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const VPValue *getSingleOperandOrNull(const VPUser &U) {
|
||||
if (U.getNumOperands() == 1)
|
||||
return U.getOperand(0);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void resetSingleOpUser(VPUser &U, VPValue *NewVal) {
|
||||
assert(U.getNumOperands() <= 1 && "Didn't expect more than one operand!");
|
||||
if (!NewVal) {
|
||||
if (U.getNumOperands() == 1)
|
||||
U.removeLastOperand();
|
||||
return;
|
||||
}
|
||||
|
||||
if (U.getNumOperands() == 1)
|
||||
U.setOperand(0, NewVal);
|
||||
else
|
||||
U.addOperand(NewVal);
|
||||
}
|
||||
|
||||
VPValue *VPBlockBase::getCondBit() {
|
||||
return getSingleOperandOrNull(CondBitUser);
|
||||
return CondBitUser.getSingleOperandOrNull();
|
||||
}
|
||||
|
||||
const VPValue *VPBlockBase::getCondBit() const {
|
||||
return getSingleOperandOrNull(CondBitUser);
|
||||
return CondBitUser.getSingleOperandOrNull();
|
||||
}
|
||||
|
||||
void VPBlockBase::setCondBit(VPValue *CV) {
|
||||
resetSingleOpUser(CondBitUser, CV);
|
||||
}
|
||||
void VPBlockBase::setCondBit(VPValue *CV) { CondBitUser.resetSingleOpUser(CV); }
|
||||
|
||||
VPValue *VPBlockBase::getPredicate() {
|
||||
return getSingleOperandOrNull(PredicateUser);
|
||||
return PredicateUser.getSingleOperandOrNull();
|
||||
}
|
||||
|
||||
const VPValue *VPBlockBase::getPredicate() const {
|
||||
return getSingleOperandOrNull(PredicateUser);
|
||||
return PredicateUser.getSingleOperandOrNull();
|
||||
}
|
||||
|
||||
void VPBlockBase::setPredicate(VPValue *CV) {
|
||||
resetSingleOpUser(PredicateUser, CV);
|
||||
PredicateUser.resetSingleOpUser(CV);
|
||||
}
|
||||
|
||||
void VPBlockBase::deleteCFG(VPBlockBase *Entry) {
|
||||
|
|
|
@ -341,6 +341,41 @@ struct VPTransformState {
|
|||
VPlan *Plan;
|
||||
};
|
||||
|
||||
/// VPUsers instance used by VPBlockBase to manage CondBit and the block
|
||||
/// predicate. Currently VPBlockUsers are used in VPBlockBase for historical
|
||||
/// reasons, but in the future the only VPUsers should either be recipes or
|
||||
/// live-outs.VPBlockBase uses.
|
||||
struct VPBlockUser : public VPUser {
|
||||
VPBlockUser() : VPUser({}, VPUserID::Block) {}
|
||||
|
||||
VPValue *getSingleOperandOrNull() {
|
||||
if (getNumOperands() == 1)
|
||||
return getOperand(0);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
const VPValue *getSingleOperandOrNull() const {
|
||||
if (getNumOperands() == 1)
|
||||
return getOperand(0);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void resetSingleOpUser(VPValue *NewVal) {
|
||||
assert(getNumOperands() <= 1 && "Didn't expect more than one operand!");
|
||||
if (!NewVal) {
|
||||
if (getNumOperands() == 1)
|
||||
removeLastOperand();
|
||||
return;
|
||||
}
|
||||
|
||||
if (getNumOperands() == 1)
|
||||
setOperand(0, NewVal);
|
||||
else
|
||||
addOperand(NewVal);
|
||||
}
|
||||
};
|
||||
|
||||
/// VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
|
||||
/// A VPBlockBase can be either a VPBasicBlock or a VPRegionBlock.
|
||||
class VPBlockBase {
|
||||
|
@ -364,12 +399,12 @@ class VPBlockBase {
|
|||
/// Successor selector managed by a VPUser. For blocks with zero or one
|
||||
/// successors, there is no operand. Otherwise there is exactly one operand
|
||||
/// which is the branch condition.
|
||||
VPUser CondBitUser;
|
||||
VPBlockUser CondBitUser;
|
||||
|
||||
/// If the block is predicated, its predicate is stored as an operand of this
|
||||
/// VPUser to maintain the def-use relations. Otherwise there is no operand
|
||||
/// here.
|
||||
VPUser PredicateUser;
|
||||
VPBlockUser PredicateUser;
|
||||
|
||||
/// VPlan containing the block. Can only be set on the entry block of the
|
||||
/// plan.
|
||||
|
@ -621,17 +656,16 @@ class VPRecipeBase : public ilist_node_with_parent<VPRecipeBase, VPBasicBlock>,
|
|||
friend VPBasicBlock;
|
||||
friend class VPBlockUtils;
|
||||
|
||||
|
||||
/// Each VPRecipe belongs to a single VPBasicBlock.
|
||||
VPBasicBlock *Parent = nullptr;
|
||||
|
||||
public:
|
||||
VPRecipeBase(const unsigned char SC, ArrayRef<VPValue *> Operands)
|
||||
: VPDef(SC), VPUser(Operands) {}
|
||||
: VPDef(SC), VPUser(Operands, VPUser::VPUserID::Recipe) {}
|
||||
|
||||
template <typename IterT>
|
||||
VPRecipeBase(const unsigned char SC, iterator_range<IterT> Operands)
|
||||
: VPDef(SC), VPUser(Operands) {}
|
||||
: VPDef(SC), VPUser(Operands, VPUser::VPUserID::Recipe) {}
|
||||
virtual ~VPRecipeBase() = default;
|
||||
|
||||
/// \return the VPBasicBlock which this VPRecipe belongs to.
|
||||
|
@ -683,6 +717,10 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
static inline bool classof(const VPUser *U) {
|
||||
return U->getVPUserID() == VPUser::VPUserID::Recipe;
|
||||
}
|
||||
|
||||
/// Returns true if the recipe may have side-effects.
|
||||
bool mayHaveSideEffects() const;
|
||||
|
||||
|
|
|
@ -191,28 +191,42 @@ raw_ostream &operator<<(raw_ostream &OS, const VPValue &V);
|
|||
/// This class augments VPValue with operands which provide the inverse def-use
|
||||
/// edges from VPValue's users to their defs.
|
||||
class VPUser {
|
||||
public:
|
||||
/// Subclass identifier (for isa/dyn_cast).
|
||||
enum class VPUserID {
|
||||
Recipe,
|
||||
// TODO: Currently VPUsers are used in VPBlockBase, but in the future the
|
||||
// only VPUsers should either be recipes or live-outs.
|
||||
Block
|
||||
};
|
||||
|
||||
private:
|
||||
SmallVector<VPValue *, 2> Operands;
|
||||
|
||||
VPUserID ID;
|
||||
|
||||
protected:
|
||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
||||
/// Print the operands to \p O.
|
||||
void printOperands(raw_ostream &O, VPSlotTracker &SlotTracker) const;
|
||||
#endif
|
||||
|
||||
VPUser(ArrayRef<VPValue *> Operands, VPUserID ID) : ID(ID) {
|
||||
for (VPValue *Operand : Operands)
|
||||
addOperand(Operand);
|
||||
}
|
||||
|
||||
VPUser(std::initializer_list<VPValue *> Operands, VPUserID ID)
|
||||
: VPUser(ArrayRef<VPValue *>(Operands), ID) {}
|
||||
|
||||
template <typename IterT>
|
||||
VPUser(iterator_range<IterT> Operands, VPUserID ID) : ID(ID) {
|
||||
for (VPValue *Operand : Operands)
|
||||
addOperand(Operand);
|
||||
}
|
||||
|
||||
public:
|
||||
VPUser() {}
|
||||
VPUser(ArrayRef<VPValue *> Operands) {
|
||||
for (VPValue *Operand : Operands)
|
||||
addOperand(Operand);
|
||||
}
|
||||
|
||||
VPUser(std::initializer_list<VPValue *> Operands)
|
||||
: VPUser(ArrayRef<VPValue *>(Operands)) {}
|
||||
template <typename IterT> VPUser(iterator_range<IterT> Operands) {
|
||||
for (VPValue *Operand : Operands)
|
||||
addOperand(Operand);
|
||||
}
|
||||
|
||||
VPUser() = delete;
|
||||
VPUser(const VPUser &) = delete;
|
||||
VPUser &operator=(const VPUser &) = delete;
|
||||
virtual ~VPUser() {
|
||||
|
@ -220,6 +234,8 @@ public:
|
|||
Op->removeUser(*this);
|
||||
}
|
||||
|
||||
VPUserID getVPUserID() const { return ID; }
|
||||
|
||||
void addOperand(VPValue *Operand) {
|
||||
Operands.push_back(Operand);
|
||||
Operand->addUser(*this);
|
||||
|
|
Loading…
Reference in New Issue