| //===- VPlanValue.h - Represent Values in Vectorizer Plan -----------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| /// | |
| /// \file | |
| /// This file contains the declarations of the entities induced by Vectorization | |
| /// Plans, e.g. the instructions the VPlan intends to generate if executed. | |
| /// VPlan models the following entities: | |
| /// VPValue | |
| /// |-- VPUser | |
| /// | |-- VPInstruction | |
| /// These are documented in docs/VectorizationPlan.rst. | |
| /// | |
| //===----------------------------------------------------------------------===// | |
| #ifndef LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H | |
| #define LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H | |
| #include "llvm/ADT/DenseMap.h" | |
| #include "llvm/ADT/SmallVector.h" | |
| #include "llvm/IR/Value.h" | |
| #include "llvm/Support/Debug.h" | |
| #include "llvm/Support/raw_ostream.h" | |
| namespace llvm { | |
| // Forward declarations. | |
| class VPUser; | |
| // This is the base class of the VPlan Def/Use graph, used for modeling the data | |
| // flow into, within and out of the VPlan. VPValues can stand for live-ins | |
| // coming from the input IR, instructions which VPlan will generate if executed | |
| // and live-outs which the VPlan will need to fix accordingly. | |
| class VPValue { | |
| friend class VPBuilder; | |
| friend class VPlanHCFGTransforms; | |
| friend class VPBasicBlock; | |
| friend class VPInterleavedAccessInfo; | |
| private: | |
| const unsigned char SubclassID; ///< Subclass identifier (for isa/dyn_cast). | |
| SmallVector<VPUser *, 1> Users; | |
| protected: | |
| // Hold the underlying Value, if any, attached to this VPValue. | |
| Value *UnderlyingVal; | |
| VPValue(const unsigned char SC, Value *UV = nullptr) | |
| : SubclassID(SC), UnderlyingVal(UV) {} | |
| // DESIGN PRINCIPLE: Access to the underlying IR must be strictly limited to | |
| // the front-end and back-end of VPlan so that the middle-end is as | |
| // independent as possible of the underlying IR. We grant access to the | |
| // underlying IR using friendship. In that way, we should be able to use VPlan | |
| // for multiple underlying IRs (Polly?) by providing a new VPlan front-end, | |
| // back-end and analysis information for the new IR. | |
| /// Return the underlying Value attached to this VPValue. | |
| Value *getUnderlyingValue() { return UnderlyingVal; } | |
| // Set \p Val as the underlying Value of this VPValue. | |
| void setUnderlyingValue(Value *Val) { | |
| assert(!UnderlyingVal && "Underlying Value is already set."); | |
| UnderlyingVal = Val; | |
| } | |
| public: | |
| /// An enumeration for keeping track of the concrete subclass of VPValue that | |
| /// are actually instantiated. Values of this enumeration are kept in the | |
| /// SubclassID field of the VPValue objects. They are used for concrete | |
| /// type identification. | |
| enum { VPValueSC, VPUserSC, VPInstructionSC }; | |
| VPValue(Value *UV = nullptr) : VPValue(VPValueSC, UV) {} | |
| VPValue(const VPValue &) = delete; | |
| VPValue &operator=(const VPValue &) = delete; | |
| /// \return an ID for the concrete type of this object. | |
| /// This is used to implement the classof checks. This should not be used | |
| /// for any other purpose, as the values may change as LLVM evolves. | |
| unsigned getVPValueID() const { return SubclassID; } | |
| void printAsOperand(raw_ostream &OS) const { | |
| OS << "%vp" << (unsigned short)(unsigned long long)this; | |
| } | |
| unsigned getNumUsers() const { return Users.size(); } | |
| void addUser(VPUser &User) { Users.push_back(&User); } | |
| typedef SmallVectorImpl<VPUser *>::iterator user_iterator; | |
| typedef SmallVectorImpl<VPUser *>::const_iterator const_user_iterator; | |
| typedef iterator_range<user_iterator> user_range; | |
| typedef iterator_range<const_user_iterator> const_user_range; | |
| user_iterator user_begin() { return Users.begin(); } | |
| const_user_iterator user_begin() const { return Users.begin(); } | |
| user_iterator user_end() { return Users.end(); } | |
| const_user_iterator user_end() const { return Users.end(); } | |
| user_range users() { return user_range(user_begin(), user_end()); } | |
| const_user_range users() const { | |
| return const_user_range(user_begin(), user_end()); | |
| } | |
| /// Returns true if the value has more than one unique user. | |
| bool hasMoreThanOneUniqueUser() { | |
| if (getNumUsers() == 0) | |
| return false; | |
| // Check if all users match the first user. | |
| auto Current = std::next(user_begin()); | |
| while (Current != user_end() && *user_begin() == *Current) | |
| Current++; | |
| return Current != user_end(); | |
| } | |
| void replaceAllUsesWith(VPValue *New); | |
| }; | |
| typedef DenseMap<Value *, VPValue *> Value2VPValueTy; | |
| typedef DenseMap<VPValue *, Value *> VPValue2ValueTy; | |
| 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 VPValue { | |
| private: | |
| SmallVector<VPValue *, 2> Operands; | |
| protected: | |
| VPUser(const unsigned char SC) : VPValue(SC) {} | |
| VPUser(const unsigned char SC, ArrayRef<VPValue *> Operands) : VPValue(SC) { | |
| for (VPValue *Operand : Operands) | |
| addOperand(Operand); | |
| } | |
| public: | |
| VPUser() : VPValue(VPValue::VPUserSC) {} | |
| VPUser(ArrayRef<VPValue *> Operands) : VPUser(VPValue::VPUserSC, Operands) {} | |
| VPUser(std::initializer_list<VPValue *> Operands) | |
| : VPUser(ArrayRef<VPValue *>(Operands)) {} | |
| VPUser(const VPUser &) = delete; | |
| VPUser &operator=(const VPUser &) = delete; | |
| /// Method to support type inquiry through isa, cast, and dyn_cast. | |
| static inline bool classof(const VPValue *V) { | |
| return V->getVPValueID() >= VPUserSC && | |
| V->getVPValueID() <= VPInstructionSC; | |
| } | |
| void addOperand(VPValue *Operand) { | |
| Operands.push_back(Operand); | |
| Operand->addUser(*this); | |
| } | |
| unsigned getNumOperands() const { return Operands.size(); } | |
| inline VPValue *getOperand(unsigned N) const { | |
| assert(N < Operands.size() && "Operand index out of bounds"); | |
| return Operands[N]; | |
| } | |
| void setOperand(unsigned I, VPValue *New) { Operands[I] = New; } | |
| typedef SmallVectorImpl<VPValue *>::iterator operand_iterator; | |
| typedef SmallVectorImpl<VPValue *>::const_iterator const_operand_iterator; | |
| typedef iterator_range<operand_iterator> operand_range; | |
| typedef iterator_range<const_operand_iterator> const_operand_range; | |
| operand_iterator op_begin() { return Operands.begin(); } | |
| const_operand_iterator op_begin() const { return Operands.begin(); } | |
| operand_iterator op_end() { return Operands.end(); } | |
| const_operand_iterator op_end() const { return Operands.end(); } | |
| operand_range operands() { return operand_range(op_begin(), op_end()); } | |
| const_operand_range operands() const { | |
| return const_operand_range(op_begin(), op_end()); | |
| } | |
| }; | |
| } // namespace llvm | |
| #endif // LLVM_TRANSFORMS_VECTORIZE_VPLAN_VALUE_H |