diff options
Diffstat (limited to 'include/llvm/CodeGen/SelectionDAGNodes.h')
-rw-r--r-- | include/llvm/CodeGen/SelectionDAGNodes.h | 507 |
1 files changed, 157 insertions, 350 deletions
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 536fc656e8e2..cfcc4117f93b 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -44,7 +44,7 @@ class GlobalValue; class MachineBasicBlock; class MachineConstantPoolValue; class SDNode; -class BinaryWithFlagsSDNode; +class HandleSDNode; class Value; class MCSymbol; template <typename T> struct DenseMapInfo; @@ -66,24 +66,28 @@ struct SDVTList { namespace ISD { /// Node predicates - /// Return true if the specified node is a - /// BUILD_VECTOR where all of the elements are ~0 or undef. + /// If N is a BUILD_VECTOR node whose elements are all the same constant or + /// undefined, return true and return the constant value in \p SplatValue. + bool isConstantSplatVector(const SDNode *N, APInt &SplatValue); + + /// Return true if the specified node is a BUILD_VECTOR where all of the + /// elements are ~0 or undef. bool isBuildVectorAllOnes(const SDNode *N); - /// Return true if the specified node is a - /// BUILD_VECTOR where all of the elements are 0 or undef. + /// Return true if the specified node is a BUILD_VECTOR where all of the + /// elements are 0 or undef. bool isBuildVectorAllZeros(const SDNode *N); - /// \brief Return true if the specified node is a BUILD_VECTOR node of - /// all ConstantSDNode or undef. + /// Return true if the specified node is a BUILD_VECTOR node of all + /// ConstantSDNode or undef. bool isBuildVectorOfConstantSDNodes(const SDNode *N); - /// \brief Return true if the specified node is a BUILD_VECTOR node of - /// all ConstantFPSDNode or undef. + /// Return true if the specified node is a BUILD_VECTOR node of all + /// ConstantFPSDNode or undef. bool isBuildVectorOfConstantFPSDNodes(const SDNode *N); - /// Return true if the node has at least one operand - /// and all operands of the specified node are ISD::UNDEF. + /// Return true if the node has at least one operand and all operands of the + /// specified node are ISD::UNDEF. bool allOperandsUndef(const SDNode *N); } // end llvm:ISD namespace @@ -280,6 +284,8 @@ public: private: friend class SelectionDAG; friend class SDNode; + // TODO: unfriend HandleSDNode once we fix its operand handling. + friend class HandleSDNode; void setUser(SDNode *p) { User = p; } @@ -328,6 +334,7 @@ private: bool NoInfs : 1; bool NoSignedZeros : 1; bool AllowReciprocal : 1; + bool VectorReduction : 1; public: /// Default constructor turns off all optimization flags. @@ -340,6 +347,7 @@ public: NoInfs = false; NoSignedZeros = false; AllowReciprocal = false; + VectorReduction = false; } // These are mutators for each flag. @@ -351,6 +359,7 @@ public: void setNoInfs(bool b) { NoInfs = b; } void setNoSignedZeros(bool b) { NoSignedZeros = b; } void setAllowReciprocal(bool b) { AllowReciprocal = b; } + void setVectorReduction(bool b) { VectorReduction = b; } // These are accessors for each flag. bool hasNoUnsignedWrap() const { return NoUnsignedWrap; } @@ -361,6 +370,7 @@ public: bool hasNoInfs() const { return NoInfs; } bool hasNoSignedZeros() const { return NoSignedZeros; } bool hasAllowReciprocal() const { return AllowReciprocal; } + bool hasVectorReduction() const { return VectorReduction; } /// Return a raw encoding of the flags. /// This function should only be used to add data to the NodeID value. @@ -390,10 +400,6 @@ private: /// The operation that this node performs. int16_t NodeType; - /// This is true if OperandList was new[]'d. If true, - /// then they will be delete[]'d when the node is destroyed. - uint16_t OperandsNeedDelete : 1; - /// This tracks whether this node has one or more dbg_value /// nodes corresponding to it. uint16_t HasDebugValue : 1; @@ -402,7 +408,7 @@ protected: /// This member is defined by this class, but is not used for /// anything. Subclasses can use it to hold whatever state they find useful. /// This field is initialized to zero by the ctor. - uint16_t SubclassData : 14; + uint16_t SubclassData : 15; private: /// Unique id per SDNode in the DAG. @@ -436,6 +442,8 @@ private: friend class SelectionDAG; friend struct ilist_traits<SDNode>; + // TODO: unfriend HandleSDNode once we fix its operand handling. + friend class HandleSDNode; public: /// Unique and persistent id per SDNode in the DAG. @@ -621,18 +629,32 @@ public: /// NOTE: This is an expensive method. Use it carefully. bool hasPredecessor(const SDNode *N) const; - /// Return true if N is a predecessor of this node. - /// N is either an operand of this node, or can be reached by recursively - /// traversing up the operands. - /// In this helper the Visited and worklist sets are held externally to - /// cache predecessors over multiple invocations. If you want to test for - /// multiple predecessors this method is preferable to multiple calls to - /// hasPredecessor. Be sure to clear Visited and Worklist if the DAG - /// changes. - /// NOTE: This is still very expensive. Use carefully. - bool hasPredecessorHelper(const SDNode *N, - SmallPtrSetImpl<const SDNode *> &Visited, - SmallVectorImpl<const SDNode *> &Worklist) const; + /// Returns true if N is a predecessor of any node in Worklist. This + /// helper keeps Visited and Worklist sets externally to allow unions + /// searches to be performed in parallel, caching of results across + /// queries and incremental addition to Worklist. Stops early if N is + /// found but will resume. Remember to clear Visited and Worklists + /// if DAG changes. + static bool hasPredecessorHelper(const SDNode *N, + SmallPtrSetImpl<const SDNode *> &Visited, + SmallVectorImpl<const SDNode *> &Worklist) { + if (Visited.count(N)) + return true; + while (!Worklist.empty()) { + const SDNode *M = Worklist.pop_back_val(); + bool Found = false; + for (const SDValue &OpV : M->op_values()) { + SDNode *Op = OpV.getNode(); + if (Visited.insert(Op).second) + Worklist.push_back(Op); + if (Op == N) + Found = true; + } + if (Found) + return true; + } + return false; + } /// Return the number of values used by this operation. unsigned getNumOperands() const { return NumOperands; } @@ -788,101 +810,20 @@ protected: return Ret; } - SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, - ArrayRef<SDValue> Ops) - : NodeType(Opc), OperandsNeedDelete(true), HasDebugValue(false), - SubclassData(0), NodeId(-1), - OperandList(Ops.size() ? new SDUse[Ops.size()] : nullptr), - ValueList(VTs.VTs), UseList(nullptr), NumOperands(Ops.size()), - NumValues(VTs.NumVTs), IROrder(Order), debugLoc(std::move(dl)) { - assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); - assert(NumOperands == Ops.size() && - "NumOperands wasn't wide enough for its operands!"); - assert(NumValues == VTs.NumVTs && - "NumValues wasn't wide enough for its operands!"); - for (unsigned i = 0; i != Ops.size(); ++i) { - assert(OperandList && "no operands available"); - OperandList[i].setUser(this); - OperandList[i].setInitial(Ops[i]); - } - checkForCycles(this); - } - - /// This constructor adds no operands itself; operands can be - /// set later with InitOperands. + /// Create an SDNode. + /// + /// SDNodes are created without any operands, and never own the operand + /// storage. To add operands, see SelectionDAG::createOperands. SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs) - : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false), - SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs), - UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), - IROrder(Order), debugLoc(std::move(dl)) { + : NodeType(Opc), HasDebugValue(false), SubclassData(0), NodeId(-1), + OperandList(nullptr), ValueList(VTs.VTs), UseList(nullptr), + NumOperands(0), NumValues(VTs.NumVTs), IROrder(Order), + debugLoc(std::move(dl)) { assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); assert(NumValues == VTs.NumVTs && "NumValues wasn't wide enough for its operands!"); } - /// Initialize the operands list of this with 1 operand. - void InitOperands(SDUse *Ops, const SDValue &Op0) { - Ops[0].setUser(this); - Ops[0].setInitial(Op0); - NumOperands = 1; - OperandList = Ops; - checkForCycles(this); - } - - /// Initialize the operands list of this with 2 operands. - void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1) { - Ops[0].setUser(this); - Ops[0].setInitial(Op0); - Ops[1].setUser(this); - Ops[1].setInitial(Op1); - NumOperands = 2; - OperandList = Ops; - checkForCycles(this); - } - - /// Initialize the operands list of this with 3 operands. - void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1, - const SDValue &Op2) { - Ops[0].setUser(this); - Ops[0].setInitial(Op0); - Ops[1].setUser(this); - Ops[1].setInitial(Op1); - Ops[2].setUser(this); - Ops[2].setInitial(Op2); - NumOperands = 3; - OperandList = Ops; - checkForCycles(this); - } - - /// Initialize the operands list of this with 4 operands. - void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1, - const SDValue &Op2, const SDValue &Op3) { - Ops[0].setUser(this); - Ops[0].setInitial(Op0); - Ops[1].setUser(this); - Ops[1].setInitial(Op1); - Ops[2].setUser(this); - Ops[2].setInitial(Op2); - Ops[3].setUser(this); - Ops[3].setInitial(Op3); - NumOperands = 4; - OperandList = Ops; - checkForCycles(this); - } - - /// Initialize the operands list of this with N operands. - void InitOperands(SDUse *Ops, const SDValue *Vals, unsigned N) { - for (unsigned i = 0; i != N; ++i) { - Ops[i].setUser(this); - Ops[i].setInitial(Vals[i]); - } - NumOperands = N; - assert(NumOperands == N && - "NumOperands wasn't wide enough for its operands!"); - OperandList = Ops; - checkForCycles(this); - } - /// Release the operands and set this node to have zero operands. void DropOperands(); }; @@ -898,40 +839,20 @@ protected: /// be used by the DAGBuilder, the other to be used by others. class SDLoc { private: - // Ptr could be used for either Instruction* or SDNode*. It is used for - // Instruction* if IROrder is not -1. - const void *Ptr; - int IROrder; + DebugLoc DL; + int IROrder = 0; public: - SDLoc() : Ptr(nullptr), IROrder(0) {} - SDLoc(const SDNode *N) : Ptr(N), IROrder(-1) { - assert(N && "null SDNode"); - } - SDLoc(const SDValue V) : Ptr(V.getNode()), IROrder(-1) { - assert(Ptr && "null SDNode"); - } - SDLoc(const Instruction *I, int Order) : Ptr(I), IROrder(Order) { + SDLoc() = default; + SDLoc(const SDNode *N) : DL(N->getDebugLoc()), IROrder(N->getIROrder()) {} + SDLoc(const SDValue V) : SDLoc(V.getNode()) {} + SDLoc(const Instruction *I, int Order) : IROrder(Order) { assert(Order >= 0 && "bad IROrder"); + if (I) + DL = I->getDebugLoc(); } - unsigned getIROrder() { - if (IROrder >= 0 || Ptr == nullptr) { - return (unsigned)IROrder; - } - const SDNode *N = (const SDNode*)(Ptr); - return N->getIROrder(); - } - DebugLoc getDebugLoc() { - if (!Ptr) { - return DebugLoc(); - } - if (IROrder >= 0) { - const Instruction *I = (const Instruction*)(Ptr); - return I->getDebugLoc(); - } - const SDNode *N = (const SDNode*)(Ptr); - return N->getDebugLoc(); - } + unsigned getIROrder() const { return IROrder; } + const DebugLoc &getDebugLoc() const { return DL; } }; @@ -1008,30 +929,6 @@ inline void SDUse::setNode(SDNode *N) { if (N) N->addUse(*this); } -/// This class is used for single-operand SDNodes. This is solely -/// to allow co-allocation of node operands with the node itself. -class UnarySDNode : public SDNode { - SDUse Op; -public: - UnarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, - SDValue X) - : SDNode(Opc, Order, dl, VTs) { - InitOperands(&Op, X); - } -}; - -/// This class is used for two-operand SDNodes. This is solely -/// to allow co-allocation of node operands with the node itself. -class BinarySDNode : public SDNode { - SDUse Ops[2]; -public: - BinarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, - SDValue X, SDValue Y) - : SDNode(Opc, Order, dl, VTs) { - InitOperands(Ops, X, Y); - } -}; - /// Returns true if the opcode is a binary operation with flags. static bool isBinOpWithFlags(unsigned Opcode) { switch (Opcode) { @@ -1056,30 +953,17 @@ static bool isBinOpWithFlags(unsigned Opcode) { /// This class is an extension of BinarySDNode /// used from those opcodes that have associated extra flags. -class BinaryWithFlagsSDNode : public BinarySDNode { +class BinaryWithFlagsSDNode : public SDNode { public: SDNodeFlags Flags; - BinaryWithFlagsSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, - SDValue X, SDValue Y, const SDNodeFlags &NodeFlags) - : BinarySDNode(Opc, Order, dl, VTs, X, Y), Flags(NodeFlags) {} + BinaryWithFlagsSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, + SDVTList VTs, const SDNodeFlags &NodeFlags) + : SDNode(Opc, Order, dl, VTs), Flags(NodeFlags) {} static bool classof(const SDNode *N) { return isBinOpWithFlags(N->getOpcode()); } }; -/// This class is used for three-operand SDNodes. This is solely -/// to allow co-allocation of node operands with the node itself. -class TernarySDNode : public SDNode { - SDUse Ops[3]; -public: - TernarySDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, - SDValue X, SDValue Y, SDValue Z) - : SDNode(Opc, Order, dl, VTs) { - InitOperands(Ops, X, Y, Z); - } -}; - - /// This class is used to form a handle around another node that /// is persistent and is updated across invocations of replaceAllUsesWith on its /// operand. This node should be directly created by end-users and not added to @@ -1092,19 +976,27 @@ public: // HandleSDNodes are never inserted into the DAG, so they won't be // auto-numbered. Use ID 65535 as a sentinel. PersistentId = 0xffff; - InitOperands(&Op, X); + + // Manually set up the operand list. This node type is special in that it's + // always stack allocated and SelectionDAG does not manage its operands. + // TODO: This should either (a) not be in the SDNode hierarchy, or (b) not + // be so special. + Op.setUser(this); + Op.setInitial(X); + NumOperands = 1; + OperandList = &Op; } ~HandleSDNode(); const SDValue &getValue() const { return Op; } }; -class AddrSpaceCastSDNode : public UnarySDNode { +class AddrSpaceCastSDNode : public SDNode { private: unsigned SrcAddrSpace; unsigned DestAddrSpace; public: - AddrSpaceCastSDNode(unsigned Order, DebugLoc dl, EVT VT, SDValue X, + AddrSpaceCastSDNode(unsigned Order, const DebugLoc &dl, EVT VT, unsigned SrcAS, unsigned DestAS); unsigned getSrcAddressSpace() const { return SrcAddrSpace; } @@ -1126,12 +1018,9 @@ protected: MachineMemOperand *MMO; public: - MemSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, + MemSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, SDVTList VTs, EVT MemoryVT, MachineMemOperand *MMO); - MemSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, - ArrayRef<SDValue> Ops, EVT MemoryVT, MachineMemOperand *MMO); - bool readMem() const { return MMO->isLoad(); } bool writeMem() const { return MMO->isStore(); } @@ -1234,8 +1123,6 @@ public: /// This is an SDNode representing atomic operations. class AtomicSDNode : public MemSDNode { - SDUse Ops[4]; - /// For cmpxchg instructions, the ordering requirements when a store does not /// occur. AtomicOrdering FailureOrdering; @@ -1244,13 +1131,15 @@ class AtomicSDNode : public MemSDNode { AtomicOrdering FailureOrdering, SynchronizationScope SynchScope) { // This must match encodeMemSDNodeFlags() in SelectionDAG.cpp. - assert((SuccessOrdering & 15) == SuccessOrdering && + assert((AtomicOrdering)((unsigned)SuccessOrdering & 15) == + SuccessOrdering && "Ordering may not require more than 4 bits!"); - assert((FailureOrdering & 15) == FailureOrdering && + assert((AtomicOrdering)((unsigned)FailureOrdering & 15) == + FailureOrdering && "Ordering may not require more than 4 bits!"); assert((SynchScope & 1) == SynchScope && "SynchScope may not require more than 1 bit!"); - SubclassData |= SuccessOrdering << 8; + SubclassData |= (unsigned)SuccessOrdering << 8; SubclassData |= SynchScope << 12; this->FailureOrdering = FailureOrdering; assert(getSuccessOrdering() == SuccessOrdering && @@ -1261,50 +1150,12 @@ class AtomicSDNode : public MemSDNode { } public: - // Opc: opcode for atomic - // VTL: value type list - // Chain: memory chain for operaand - // Ptr: address to update as a SDValue - // Cmp: compare value - // Swp: swap value - // SrcVal: address to update as a Value (used for MemOperand) - // Align: alignment of memory - AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, - EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, - MachineMemOperand *MMO, AtomicOrdering Ordering, - SynchronizationScope SynchScope) - : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { - InitAtomic(Ordering, Ordering, SynchScope); - InitOperands(Ops, Chain, Ptr, Cmp, Swp); - } - AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, - EVT MemVT, - SDValue Chain, SDValue Ptr, - SDValue Val, MachineMemOperand *MMO, - AtomicOrdering Ordering, SynchronizationScope SynchScope) - : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { - InitAtomic(Ordering, Ordering, SynchScope); - InitOperands(Ops, Chain, Ptr, Val); - } - AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, - EVT MemVT, - SDValue Chain, SDValue Ptr, - MachineMemOperand *MMO, - AtomicOrdering Ordering, SynchronizationScope SynchScope) - : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { - InitAtomic(Ordering, Ordering, SynchScope); - InitOperands(Ops, Chain, Ptr); - } - AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, EVT MemVT, - const SDValue* AllOps, SDUse *DynOps, unsigned NumOps, - MachineMemOperand *MMO, + AtomicSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, SDVTList VTL, + EVT MemVT, MachineMemOperand *MMO, AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, SynchronizationScope SynchScope) - : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { + : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { InitAtomic(SuccessOrdering, FailureOrdering, SynchScope); - assert((DynOps || NumOps <= array_lengthof(Ops)) && - "Too many ops for internal storage!"); - InitOperands(DynOps ? DynOps : Ops, AllOps, NumOps); } const SDValue &getBasePtr() const { return getOperand(1); } @@ -1351,10 +1202,9 @@ public: /// with a value not less than FIRST_TARGET_MEMORY_OPCODE. class MemIntrinsicSDNode : public MemSDNode { public: - MemIntrinsicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, - ArrayRef<SDValue> Ops, EVT MemoryVT, - MachineMemOperand *MMO) - : MemSDNode(Opc, Order, dl, VTs, Ops, MemoryVT, MMO) { + MemIntrinsicSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, + SDVTList VTs, EVT MemoryVT, MachineMemOperand *MMO) + : MemSDNode(Opc, Order, dl, VTs, MemoryVT, MMO) { SubclassData |= 1u << 13; } @@ -1377,20 +1227,15 @@ public: /// An index of -1 is treated as undef, such that the code generator may put /// any value in the corresponding element of the result. class ShuffleVectorSDNode : public SDNode { - SDUse Ops[2]; - // The memory for Mask is owned by the SelectionDAG's OperandAllocator, and // is freed when the SelectionDAG object is destroyed. const int *Mask; protected: friend class SelectionDAG; - ShuffleVectorSDNode(EVT VT, unsigned Order, DebugLoc dl, SDValue N1, - SDValue N2, const int *M) - : SDNode(ISD::VECTOR_SHUFFLE, Order, dl, getSDVTList(VT)), Mask(M) { - InitOperands(Ops, N1, N2); - } -public: + ShuffleVectorSDNode(EVT VT, unsigned Order, const DebugLoc &dl, const int *M) + : SDNode(ISD::VECTOR_SHUFFLE, Order, dl, getSDVTList(VT)), Mask(M) {} +public: ArrayRef<int> getMask() const { EVT VT = getValueType(0); return makeArrayRef(Mask, VT.getVectorNumElements()); @@ -1414,7 +1259,7 @@ public: /// Change values in a shuffle permute mask assuming /// the two vector operands have swapped position. - static void commuteMask(SmallVectorImpl<int> &Mask) { + static void commuteMask(MutableArrayRef<int> Mask) { unsigned NumElems = Mask.size(); for (unsigned i = 0; i != NumElems; ++i) { int idx = Mask[i]; @@ -1436,9 +1281,10 @@ class ConstantSDNode : public SDNode { const ConstantInt *Value; friend class SelectionDAG; ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val, - DebugLoc DL, EVT VT) - : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, - 0, DL, getSDVTList(VT)), Value(val) { + const DebugLoc &DL, EVT VT) + : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, 0, DL, + getSDVTList(VT)), + Value(val) { SubclassData |= (uint16_t)isOpaque; } public: @@ -1463,10 +1309,12 @@ public: class ConstantFPSDNode : public SDNode { const ConstantFP *Value; friend class SelectionDAG; - ConstantFPSDNode(bool isTarget, const ConstantFP *val, DebugLoc DL, EVT VT) - : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, - 0, DL, getSDVTList(VT)), Value(val) { - } + ConstantFPSDNode(bool isTarget, const ConstantFP *val, const DebugLoc &DL, + EVT VT) + : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, 0, DL, + getSDVTList(VT)), + Value(val) {} + public: const APFloat& getValueAPF() const { return Value->getValueAPF(); } @@ -1517,15 +1365,19 @@ bool isNullFPConstant(SDValue V); bool isAllOnesConstant(SDValue V); /// Returns true if \p V is a constant integer one. bool isOneConstant(SDValue V); +/// Returns true if \p V is a bitwise not operation. Assumes that an all ones +/// constant is canonicalized to be operand 1. +bool isBitwiseNot(SDValue V); class GlobalAddressSDNode : public SDNode { const GlobalValue *TheGlobal; int64_t Offset; unsigned char TargetFlags; friend class SelectionDAG; - GlobalAddressSDNode(unsigned Opc, unsigned Order, DebugLoc DL, + GlobalAddressSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL, const GlobalValue *GA, EVT VT, int64_t o, unsigned char TargetFlags); + public: const GlobalValue *getGlobal() const { return TheGlobal; } @@ -1821,13 +1673,11 @@ public: }; class EHLabelSDNode : public SDNode { - SDUse Chain; MCSymbol *Label; friend class SelectionDAG; - EHLabelSDNode(unsigned Order, DebugLoc dl, SDValue ch, MCSymbol *L) - : SDNode(ISD::EH_LABEL, Order, dl, getSDVTList(MVT::Other)), Label(L) { - InitOperands(&Chain, ch); - } + EHLabelSDNode(unsigned Order, const DebugLoc &dl, MCSymbol *L) + : SDNode(ISD::EH_LABEL, Order, dl, getSDVTList(MVT::Other)), Label(L) {} + public: MCSymbol *getLabel() const { return Label; } @@ -1892,12 +1742,11 @@ public: class CvtRndSatSDNode : public SDNode { ISD::CvtCode CvtCode; friend class SelectionDAG; - explicit CvtRndSatSDNode(EVT VT, unsigned Order, DebugLoc dl, - ArrayRef<SDValue> Ops, ISD::CvtCode Code) - : SDNode(ISD::CONVERT_RNDSAT, Order, dl, getSDVTList(VT), Ops), - CvtCode(Code) { - assert(Ops.size() == 5 && "wrong number of operations"); + explicit CvtRndSatSDNode(EVT VT, unsigned Order, const DebugLoc &dl, + ISD::CvtCode Code) + : SDNode(ISD::CONVERT_RNDSAT, Order, dl, getSDVTList(VT)), CvtCode(Code) { } + public: ISD::CvtCode getCvtCode() const { return CvtCode; } @@ -1926,24 +1775,13 @@ public: /// Base class for LoadSDNode and StoreSDNode class LSBaseSDNode : public MemSDNode { - //! Operand array for load and store - /*! - \note Moving this array to the base class captures more - common functionality shared between LoadSDNode and - StoreSDNode - */ - SDUse Ops[4]; public: - LSBaseSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl, - SDValue *Operands, unsigned numOperands, + LSBaseSDNode(ISD::NodeType NodeTy, unsigned Order, const DebugLoc &dl, SDVTList VTs, ISD::MemIndexedMode AM, EVT MemVT, MachineMemOperand *MMO) - : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { + : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { SubclassData |= AM << 2; assert(getAddressingMode() == AM && "MemIndexedMode encoding error!"); - InitOperands(Ops, Operands, numOperands); - assert((getOffset().getOpcode() == ISD::UNDEF || isIndexed()) && - "Only indexed loads and stores have a non-undef offset operand"); } const SDValue &getOffset() const { @@ -1971,10 +1809,10 @@ public: /// This class is used to represent ISD::LOAD nodes. class LoadSDNode : public LSBaseSDNode { friend class SelectionDAG; - LoadSDNode(SDValue *ChainPtrOff, unsigned Order, DebugLoc dl, SDVTList VTs, + LoadSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, ISD::MemIndexedMode AM, ISD::LoadExtType ETy, EVT MemVT, MachineMemOperand *MMO) - : LSBaseSDNode(ISD::LOAD, Order, dl, ChainPtrOff, 3, VTs, AM, MemVT, MMO) { + : LSBaseSDNode(ISD::LOAD, Order, dl, VTs, AM, MemVT, MMO) { SubclassData |= (unsigned short)ETy; assert(getExtensionType() == ETy && "LoadExtType encoding error!"); assert(readMem() && "Load MachineMemOperand is not a load!"); @@ -1999,11 +1837,10 @@ public: /// This class is used to represent ISD::STORE nodes. class StoreSDNode : public LSBaseSDNode { friend class SelectionDAG; - StoreSDNode(SDValue *ChainValuePtrOff, unsigned Order, DebugLoc dl, - SDVTList VTs, ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT, + StoreSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, + ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT, MachineMemOperand *MMO) - : LSBaseSDNode(ISD::STORE, Order, dl, ChainValuePtrOff, 4, - VTs, AM, MemVT, MMO) { + : LSBaseSDNode(ISD::STORE, Order, dl, VTs, AM, MemVT, MMO) { SubclassData |= (unsigned short)isTrunc; assert(isTruncatingStore() == isTrunc && "isTrunc encoding error!"); assert(!readMem() && "Store MachineMemOperand is a load!"); @@ -2027,16 +1864,12 @@ public: /// This base class is used to represent MLOAD and MSTORE nodes class MaskedLoadStoreSDNode : public MemSDNode { - // Operands - SDUse Ops[4]; public: friend class SelectionDAG; - MaskedLoadStoreSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl, - SDValue *Operands, unsigned numOperands, SDVTList VTs, - EVT MemVT, MachineMemOperand *MMO) - : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { - InitOperands(Ops, Operands, numOperands); - } + MaskedLoadStoreSDNode(ISD::NodeType NodeTy, unsigned Order, + const DebugLoc &dl, SDVTList VTs, EVT MemVT, + MachineMemOperand *MMO) + : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {} // In the both nodes address is Op1, mask is Op2: // MaskedLoadSDNode (Chain, ptr, mask, src0), src0 is a passthru value @@ -2055,11 +1888,9 @@ public: class MaskedLoadSDNode : public MaskedLoadStoreSDNode { public: friend class SelectionDAG; - MaskedLoadSDNode(unsigned Order, DebugLoc dl, SDValue *Operands, - unsigned numOperands, SDVTList VTs, ISD::LoadExtType ETy, - EVT MemVT, MachineMemOperand *MMO) - : MaskedLoadStoreSDNode(ISD::MLOAD, Order, dl, Operands, numOperands, - VTs, MemVT, MMO) { + MaskedLoadSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, + ISD::LoadExtType ETy, EVT MemVT, MachineMemOperand *MMO) + : MaskedLoadStoreSDNode(ISD::MLOAD, Order, dl, VTs, MemVT, MMO) { SubclassData |= (unsigned short)ETy; } @@ -2077,12 +1908,10 @@ class MaskedStoreSDNode : public MaskedLoadStoreSDNode { public: friend class SelectionDAG; - MaskedStoreSDNode(unsigned Order, DebugLoc dl, SDValue *Operands, - unsigned numOperands, SDVTList VTs, bool isTrunc, EVT MemVT, - MachineMemOperand *MMO) - : MaskedLoadStoreSDNode(ISD::MSTORE, Order, dl, Operands, numOperands, - VTs, MemVT, MMO) { - SubclassData |= (unsigned short)isTrunc; + MaskedStoreSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, + bool isTrunc, EVT MemVT, MachineMemOperand *MMO) + : MaskedLoadStoreSDNode(ISD::MSTORE, Order, dl, VTs, MemVT, MMO) { + SubclassData |= (unsigned short)isTrunc; } /// Return true if the op does a truncation before store. /// For integers this is the same as doing a TRUNCATE and storing the result. @@ -2100,17 +1929,12 @@ public: /// MGATHER and MSCATTER nodes /// class MaskedGatherScatterSDNode : public MemSDNode { - // Operands - SDUse Ops[5]; public: friend class SelectionDAG; - MaskedGatherScatterSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl, - ArrayRef<SDValue> Operands, SDVTList VTs, EVT MemVT, + MaskedGatherScatterSDNode(ISD::NodeType NodeTy, unsigned Order, + const DebugLoc &dl, SDVTList VTs, EVT MemVT, MachineMemOperand *MMO) - : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { - assert(Operands.size() == 5 && "Incompatible number of operands"); - InitOperands(Ops, Operands.data(), Operands.size()); - } + : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {} // In the both nodes address is Op1, mask is Op2: // MaskedGatherSDNode (Chain, src0, mask, base, index), src0 is a passthru value @@ -2132,19 +1956,9 @@ public: class MaskedGatherSDNode : public MaskedGatherScatterSDNode { public: friend class SelectionDAG; - MaskedGatherSDNode(unsigned Order, DebugLoc dl, ArrayRef<SDValue> Operands, - SDVTList VTs, EVT MemVT, MachineMemOperand *MMO) - : MaskedGatherScatterSDNode(ISD::MGATHER, Order, dl, Operands, VTs, MemVT, - MMO) { - assert(getValue().getValueType() == getValueType(0) && - "Incompatible type of the PassThru value in MaskedGatherSDNode"); - assert(getMask().getValueType().getVectorNumElements() == - getValueType(0).getVectorNumElements() && - "Vector width mismatch between mask and data"); - assert(getIndex().getValueType().getVectorNumElements() == - getValueType(0).getVectorNumElements() && - "Vector width mismatch between index and data"); - } + MaskedGatherSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, + EVT MemVT, MachineMemOperand *MMO) + : MaskedGatherScatterSDNode(ISD::MGATHER, Order, dl, VTs, MemVT, MMO) {} static bool classof(const SDNode *N) { return N->getOpcode() == ISD::MGATHER; @@ -2157,17 +1971,9 @@ class MaskedScatterSDNode : public MaskedGatherScatterSDNode { public: friend class SelectionDAG; - MaskedScatterSDNode(unsigned Order, DebugLoc dl,ArrayRef<SDValue> Operands, - SDVTList VTs, EVT MemVT, MachineMemOperand *MMO) - : MaskedGatherScatterSDNode(ISD::MSCATTER, Order, dl, Operands, VTs, MemVT, - MMO) { - assert(getMask().getValueType().getVectorNumElements() == - getValue().getValueType().getVectorNumElements() && - "Vector width mismatch between mask and data"); - assert(getIndex().getValueType().getVectorNumElements() == - getValue().getValueType().getVectorNumElements() && - "Vector width mismatch between index and data"); - } + MaskedScatterSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, + EVT MemVT, MachineMemOperand *MMO) + : MaskedGatherScatterSDNode(ISD::MSCATTER, Order, dl, VTs, MemVT, MMO) {} static bool classof(const SDNode *N) { return N->getOpcode() == ISD::MSCATTER; @@ -2183,12 +1989,8 @@ public: private: friend class SelectionDAG; - MachineSDNode(unsigned Opc, unsigned Order, const DebugLoc DL, SDVTList VTs) - : SDNode(Opc, Order, DL, VTs), MemRefs(nullptr), MemRefsEnd(nullptr) {} - - /// Operands for this instruction, if they fit here. If - /// they don't, this field is unused. - SDUse LocalOperands[4]; + MachineSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL, SDVTList VTs) + : SDNode(Opc, Order, DL, VTs), MemRefs(nullptr), MemRefsEnd(nullptr) {} /// Memory reference descriptions for this instruction. mmo_iterator MemRefs; @@ -2264,8 +2066,13 @@ template <> struct GraphTraits<SDNode*> { } }; -/// The largest SDNode class. -typedef MaskedGatherScatterSDNode LargestSDNode; +/// A representation of the largest SDNode, for use in sizeof(). +/// +/// This needs to be a union because the largest node differs on 32 bit systems +/// with 4 and 8 byte pointer alignment, respectively. +typedef AlignedCharArrayUnion<AtomicSDNode, TargetIndexSDNode, + BlockAddressSDNode, GlobalAddressSDNode> + LargestSDNode; /// The SDNode class with the greatest alignment requirement. typedef GlobalAddressSDNode MostAlignedSDNode; |