xref: /freebsd/contrib/llvm-project/llvm/include/llvm/CodeGen/SelectionDAGNodes.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- llvm/CodeGen/SelectionDAGNodes.h - SelectionDAG Nodes ----*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file declares the SDNode class and derived classes, which are used to
100b57cec5SDimitry Andric // represent the nodes and operations present in a SelectionDAG.  These nodes
110b57cec5SDimitry Andric // and operations are machine code level operations, with some similarities to
120b57cec5SDimitry Andric // the GCC RTL representation.
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric // Clients should include the SelectionDAG.h file instead of this file directly.
150b57cec5SDimitry Andric //
160b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric #ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H
190b57cec5SDimitry Andric #define LLVM_CODEGEN_SELECTIONDAGNODES_H
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h"
220b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
230b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h"
240b57cec5SDimitry Andric #include "llvm/ADT/FoldingSet.h"
250b57cec5SDimitry Andric #include "llvm/ADT/GraphTraits.h"
260b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
270b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
280b57cec5SDimitry Andric #include "llvm/ADT/ilist_node.h"
290b57cec5SDimitry Andric #include "llvm/ADT/iterator.h"
300b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
310b57cec5SDimitry Andric #include "llvm/CodeGen/ISDOpcodes.h"
320b57cec5SDimitry Andric #include "llvm/CodeGen/MachineMemOperand.h"
335ffd83dbSDimitry Andric #include "llvm/CodeGen/Register.h"
340b57cec5SDimitry Andric #include "llvm/CodeGen/ValueTypes.h"
35*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/MachineValueType.h"
360b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
370b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h"
380b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
390b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
400b57cec5SDimitry Andric #include "llvm/IR/Metadata.h"
410b57cec5SDimitry Andric #include "llvm/IR/Operator.h"
420b57cec5SDimitry Andric #include "llvm/Support/AlignOf.h"
430b57cec5SDimitry Andric #include "llvm/Support/AtomicOrdering.h"
440b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
450b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
46480093f4SDimitry Andric #include "llvm/Support/TypeSize.h"
470b57cec5SDimitry Andric #include <algorithm>
480b57cec5SDimitry Andric #include <cassert>
490b57cec5SDimitry Andric #include <climits>
500b57cec5SDimitry Andric #include <cstddef>
510b57cec5SDimitry Andric #include <cstdint>
520b57cec5SDimitry Andric #include <cstring>
530b57cec5SDimitry Andric #include <iterator>
540b57cec5SDimitry Andric #include <string>
550b57cec5SDimitry Andric #include <tuple>
56972a253aSDimitry Andric #include <utility>
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric namespace llvm {
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric class APInt;
610b57cec5SDimitry Andric class Constant;
620b57cec5SDimitry Andric class GlobalValue;
630b57cec5SDimitry Andric class MachineBasicBlock;
640b57cec5SDimitry Andric class MachineConstantPoolValue;
650b57cec5SDimitry Andric class MCSymbol;
660b57cec5SDimitry Andric class raw_ostream;
670b57cec5SDimitry Andric class SDNode;
680b57cec5SDimitry Andric class SelectionDAG;
690b57cec5SDimitry Andric class Type;
700b57cec5SDimitry Andric class Value;
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric void checkForCycles(const SDNode *N, const SelectionDAG *DAG = nullptr,
730b57cec5SDimitry Andric                     bool force = false);
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric /// This represents a list of ValueType's that has been intern'd by
760b57cec5SDimitry Andric /// a SelectionDAG.  Instances of this simple value class are returned by
770b57cec5SDimitry Andric /// SelectionDAG::getVTList(...).
780b57cec5SDimitry Andric ///
790b57cec5SDimitry Andric struct SDVTList {
800b57cec5SDimitry Andric   const EVT *VTs;
810b57cec5SDimitry Andric   unsigned int NumVTs;
820b57cec5SDimitry Andric };
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric namespace ISD {
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   /// Node predicates
870b57cec5SDimitry Andric 
88e8d8bef9SDimitry Andric /// If N is a BUILD_VECTOR or SPLAT_VECTOR node whose elements are all the
89e8d8bef9SDimitry Andric /// same constant or undefined, return true and return the constant value in
90e8d8bef9SDimitry Andric /// \p SplatValue.
910b57cec5SDimitry Andric bool isConstantSplatVector(const SDNode *N, APInt &SplatValue);
920b57cec5SDimitry Andric 
93e8d8bef9SDimitry Andric /// Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where
94e8d8bef9SDimitry Andric /// all of the elements are ~0 or undef. If \p BuildVectorOnly is set to
95e8d8bef9SDimitry Andric /// true, it only checks BUILD_VECTOR.
96e8d8bef9SDimitry Andric bool isConstantSplatVectorAllOnes(const SDNode *N,
97e8d8bef9SDimitry Andric                                   bool BuildVectorOnly = false);
98e8d8bef9SDimitry Andric 
99e8d8bef9SDimitry Andric /// Return true if the specified node is a BUILD_VECTOR or SPLAT_VECTOR where
100e8d8bef9SDimitry Andric /// all of the elements are 0 or undef. If \p BuildVectorOnly is set to true, it
101e8d8bef9SDimitry Andric /// only checks BUILD_VECTOR.
102e8d8bef9SDimitry Andric bool isConstantSplatVectorAllZeros(const SDNode *N,
103e8d8bef9SDimitry Andric                                    bool BuildVectorOnly = false);
104e8d8bef9SDimitry Andric 
1050b57cec5SDimitry Andric /// Return true if the specified node is a BUILD_VECTOR where all of the
1060b57cec5SDimitry Andric /// elements are ~0 or undef.
1070b57cec5SDimitry Andric bool isBuildVectorAllOnes(const SDNode *N);
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric /// Return true if the specified node is a BUILD_VECTOR where all of the
1100b57cec5SDimitry Andric /// elements are 0 or undef.
1110b57cec5SDimitry Andric bool isBuildVectorAllZeros(const SDNode *N);
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric /// Return true if the specified node is a BUILD_VECTOR node of all
1140b57cec5SDimitry Andric /// ConstantSDNode or undef.
1150b57cec5SDimitry Andric bool isBuildVectorOfConstantSDNodes(const SDNode *N);
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric /// Return true if the specified node is a BUILD_VECTOR node of all
1180b57cec5SDimitry Andric /// ConstantFPSDNode or undef.
1190b57cec5SDimitry Andric bool isBuildVectorOfConstantFPSDNodes(const SDNode *N);
1200b57cec5SDimitry Andric 
121bdd1243dSDimitry Andric /// Returns true if the specified node is a vector where all elements can
122bdd1243dSDimitry Andric /// be truncated to the specified element size without a loss in meaning.
123bdd1243dSDimitry Andric bool isVectorShrinkable(const SDNode *N, unsigned NewEltSize, bool Signed);
124bdd1243dSDimitry Andric 
1250b57cec5SDimitry Andric /// Return true if the node has at least one operand and all operands of the
1260b57cec5SDimitry Andric /// specified node are ISD::UNDEF.
1270b57cec5SDimitry Andric bool allOperandsUndef(const SDNode *N);
1280b57cec5SDimitry Andric 
129bdd1243dSDimitry Andric /// Return true if the specified node is FREEZE(UNDEF).
130bdd1243dSDimitry Andric bool isFreezeUndef(const SDNode *N);
131bdd1243dSDimitry Andric 
1320b57cec5SDimitry Andric } // end namespace ISD
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1350b57cec5SDimitry Andric /// Unlike LLVM values, Selection DAG nodes may return multiple
1360b57cec5SDimitry Andric /// values as the result of a computation.  Many nodes return multiple values,
1370b57cec5SDimitry Andric /// from loads (which define a token and a return value) to ADDC (which returns
1380b57cec5SDimitry Andric /// a result and a carry value), to calls (which may return an arbitrary number
1390b57cec5SDimitry Andric /// of values).
1400b57cec5SDimitry Andric ///
1410b57cec5SDimitry Andric /// As such, each use of a SelectionDAG computation must indicate the node that
1420b57cec5SDimitry Andric /// computes it as well as which return value to use from that node.  This pair
1430b57cec5SDimitry Andric /// of information is represented with the SDValue value type.
1440b57cec5SDimitry Andric ///
1450b57cec5SDimitry Andric class SDValue {
1460b57cec5SDimitry Andric   friend struct DenseMapInfo<SDValue>;
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   SDNode *Node = nullptr; // The node defining the value we are using.
1490b57cec5SDimitry Andric   unsigned ResNo = 0;     // Which return value of the node we are using.
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric public:
1520b57cec5SDimitry Andric   SDValue() = default;
1530b57cec5SDimitry Andric   SDValue(SDNode *node, unsigned resno);
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   /// get the index which selects a specific result in the SDNode
1560b57cec5SDimitry Andric   unsigned getResNo() const { return ResNo; }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   /// get the SDNode which holds the desired result
1590b57cec5SDimitry Andric   SDNode *getNode() const { return Node; }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   /// set the SDNode
1620b57cec5SDimitry Andric   void setNode(SDNode *N) { Node = N; }
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   inline SDNode *operator->() const { return Node; }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric   bool operator==(const SDValue &O) const {
1670b57cec5SDimitry Andric     return Node == O.Node && ResNo == O.ResNo;
1680b57cec5SDimitry Andric   }
1690b57cec5SDimitry Andric   bool operator!=(const SDValue &O) const {
1700b57cec5SDimitry Andric     return !operator==(O);
1710b57cec5SDimitry Andric   }
1720b57cec5SDimitry Andric   bool operator<(const SDValue &O) const {
1730b57cec5SDimitry Andric     return std::tie(Node, ResNo) < std::tie(O.Node, O.ResNo);
1740b57cec5SDimitry Andric   }
1750b57cec5SDimitry Andric   explicit operator bool() const {
1760b57cec5SDimitry Andric     return Node != nullptr;
1770b57cec5SDimitry Andric   }
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   SDValue getValue(unsigned R) const {
1800b57cec5SDimitry Andric     return SDValue(Node, R);
1810b57cec5SDimitry Andric   }
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   /// Return true if this node is an operand of N.
1840b57cec5SDimitry Andric   bool isOperandOf(const SDNode *N) const;
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   /// Return the ValueType of the referenced return value.
1870b57cec5SDimitry Andric   inline EVT getValueType() const;
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   /// Return the simple ValueType of the referenced return value.
1900b57cec5SDimitry Andric   MVT getSimpleValueType() const {
1910b57cec5SDimitry Andric     return getValueType().getSimpleVT();
1920b57cec5SDimitry Andric   }
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   /// Returns the size of the value in bits.
195480093f4SDimitry Andric   ///
196480093f4SDimitry Andric   /// If the value type is a scalable vector type, the scalable property will
197480093f4SDimitry Andric   /// be set and the runtime size will be a positive integer multiple of the
198480093f4SDimitry Andric   /// base size.
199480093f4SDimitry Andric   TypeSize getValueSizeInBits() const {
2000b57cec5SDimitry Andric     return getValueType().getSizeInBits();
2010b57cec5SDimitry Andric   }
2020b57cec5SDimitry Andric 
203e8d8bef9SDimitry Andric   uint64_t getScalarValueSizeInBits() const {
204e8d8bef9SDimitry Andric     return getValueType().getScalarType().getFixedSizeInBits();
2050b57cec5SDimitry Andric   }
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   // Forwarding methods - These forward to the corresponding methods in SDNode.
2080b57cec5SDimitry Andric   inline unsigned getOpcode() const;
2090b57cec5SDimitry Andric   inline unsigned getNumOperands() const;
2100b57cec5SDimitry Andric   inline const SDValue &getOperand(unsigned i) const;
2110b57cec5SDimitry Andric   inline uint64_t getConstantOperandVal(unsigned i) const;
2120b57cec5SDimitry Andric   inline const APInt &getConstantOperandAPInt(unsigned i) const;
2130b57cec5SDimitry Andric   inline bool isTargetMemoryOpcode() const;
2140b57cec5SDimitry Andric   inline bool isTargetOpcode() const;
2150b57cec5SDimitry Andric   inline bool isMachineOpcode() const;
2160b57cec5SDimitry Andric   inline bool isUndef() const;
2170b57cec5SDimitry Andric   inline unsigned getMachineOpcode() const;
2180b57cec5SDimitry Andric   inline const DebugLoc &getDebugLoc() const;
2190b57cec5SDimitry Andric   inline void dump() const;
2200b57cec5SDimitry Andric   inline void dump(const SelectionDAG *G) const;
2210b57cec5SDimitry Andric   inline void dumpr() const;
2220b57cec5SDimitry Andric   inline void dumpr(const SelectionDAG *G) const;
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric   /// Return true if this operand (which must be a chain) reaches the
2250b57cec5SDimitry Andric   /// specified operand without crossing any side-effecting instructions.
2260b57cec5SDimitry Andric   /// In practice, this looks through token factors and non-volatile loads.
2270b57cec5SDimitry Andric   /// In order to remain efficient, this only
2280b57cec5SDimitry Andric   /// looks a couple of nodes in, it does not do an exhaustive search.
2290b57cec5SDimitry Andric   bool reachesChainWithoutSideEffects(SDValue Dest,
2300b57cec5SDimitry Andric                                       unsigned Depth = 2) const;
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   /// Return true if there are no nodes using value ResNo of Node.
2330b57cec5SDimitry Andric   inline bool use_empty() const;
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   /// Return true if there is exactly one node using value ResNo of Node.
2360b57cec5SDimitry Andric   inline bool hasOneUse() const;
2370b57cec5SDimitry Andric };
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric template<> struct DenseMapInfo<SDValue> {
2400b57cec5SDimitry Andric   static inline SDValue getEmptyKey() {
2410b57cec5SDimitry Andric     SDValue V;
2420b57cec5SDimitry Andric     V.ResNo = -1U;
2430b57cec5SDimitry Andric     return V;
2440b57cec5SDimitry Andric   }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric   static inline SDValue getTombstoneKey() {
2470b57cec5SDimitry Andric     SDValue V;
2480b57cec5SDimitry Andric     V.ResNo = -2U;
2490b57cec5SDimitry Andric     return V;
2500b57cec5SDimitry Andric   }
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric   static unsigned getHashValue(const SDValue &Val) {
2530b57cec5SDimitry Andric     return ((unsigned)((uintptr_t)Val.getNode() >> 4) ^
2540b57cec5SDimitry Andric             (unsigned)((uintptr_t)Val.getNode() >> 9)) + Val.getResNo();
2550b57cec5SDimitry Andric   }
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric   static bool isEqual(const SDValue &LHS, const SDValue &RHS) {
2580b57cec5SDimitry Andric     return LHS == RHS;
2590b57cec5SDimitry Andric   }
2600b57cec5SDimitry Andric };
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric /// Allow casting operators to work directly on
2630b57cec5SDimitry Andric /// SDValues as if they were SDNode*'s.
2640b57cec5SDimitry Andric template<> struct simplify_type<SDValue> {
2650b57cec5SDimitry Andric   using SimpleType = SDNode *;
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric   static SimpleType getSimplifiedValue(SDValue &Val) {
2680b57cec5SDimitry Andric     return Val.getNode();
2690b57cec5SDimitry Andric   }
2700b57cec5SDimitry Andric };
2710b57cec5SDimitry Andric template<> struct simplify_type<const SDValue> {
2720b57cec5SDimitry Andric   using SimpleType = /*const*/ SDNode *;
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric   static SimpleType getSimplifiedValue(const SDValue &Val) {
2750b57cec5SDimitry Andric     return Val.getNode();
2760b57cec5SDimitry Andric   }
2770b57cec5SDimitry Andric };
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric /// Represents a use of a SDNode. This class holds an SDValue,
2800b57cec5SDimitry Andric /// which records the SDNode being used and the result number, a
2810b57cec5SDimitry Andric /// pointer to the SDNode using the value, and Next and Prev pointers,
2820b57cec5SDimitry Andric /// which link together all the uses of an SDNode.
2830b57cec5SDimitry Andric ///
2840b57cec5SDimitry Andric class SDUse {
2850b57cec5SDimitry Andric   /// Val - The value being used.
2860b57cec5SDimitry Andric   SDValue Val;
2870b57cec5SDimitry Andric   /// User - The user of this value.
2880b57cec5SDimitry Andric   SDNode *User = nullptr;
2890b57cec5SDimitry Andric   /// Prev, Next - Pointers to the uses list of the SDNode referred by
2900b57cec5SDimitry Andric   /// this operand.
2910b57cec5SDimitry Andric   SDUse **Prev = nullptr;
2920b57cec5SDimitry Andric   SDUse *Next = nullptr;
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric public:
2950b57cec5SDimitry Andric   SDUse() = default;
2960b57cec5SDimitry Andric   SDUse(const SDUse &U) = delete;
2970b57cec5SDimitry Andric   SDUse &operator=(const SDUse &) = delete;
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   /// Normally SDUse will just implicitly convert to an SDValue that it holds.
3000b57cec5SDimitry Andric   operator const SDValue&() const { return Val; }
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   /// If implicit conversion to SDValue doesn't work, the get() method returns
3030b57cec5SDimitry Andric   /// the SDValue.
3040b57cec5SDimitry Andric   const SDValue &get() const { return Val; }
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric   /// This returns the SDNode that contains this Use.
3070b57cec5SDimitry Andric   SDNode *getUser() { return User; }
308bdd1243dSDimitry Andric   const SDNode *getUser() const { return User; }
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric   /// Get the next SDUse in the use list.
3110b57cec5SDimitry Andric   SDUse *getNext() const { return Next; }
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric   /// Convenience function for get().getNode().
3140b57cec5SDimitry Andric   SDNode *getNode() const { return Val.getNode(); }
3150b57cec5SDimitry Andric   /// Convenience function for get().getResNo().
3160b57cec5SDimitry Andric   unsigned getResNo() const { return Val.getResNo(); }
3170b57cec5SDimitry Andric   /// Convenience function for get().getValueType().
3180b57cec5SDimitry Andric   EVT getValueType() const { return Val.getValueType(); }
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric   /// Convenience function for get().operator==
3210b57cec5SDimitry Andric   bool operator==(const SDValue &V) const {
3220b57cec5SDimitry Andric     return Val == V;
3230b57cec5SDimitry Andric   }
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric   /// Convenience function for get().operator!=
3260b57cec5SDimitry Andric   bool operator!=(const SDValue &V) const {
3270b57cec5SDimitry Andric     return Val != V;
3280b57cec5SDimitry Andric   }
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric   /// Convenience function for get().operator<
3310b57cec5SDimitry Andric   bool operator<(const SDValue &V) const {
3320b57cec5SDimitry Andric     return Val < V;
3330b57cec5SDimitry Andric   }
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric private:
3360b57cec5SDimitry Andric   friend class SelectionDAG;
3370b57cec5SDimitry Andric   friend class SDNode;
3380b57cec5SDimitry Andric   // TODO: unfriend HandleSDNode once we fix its operand handling.
3390b57cec5SDimitry Andric   friend class HandleSDNode;
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric   void setUser(SDNode *p) { User = p; }
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric   /// Remove this use from its existing use list, assign it the
3440b57cec5SDimitry Andric   /// given value, and add it to the new value's node's use list.
3450b57cec5SDimitry Andric   inline void set(const SDValue &V);
3460b57cec5SDimitry Andric   /// Like set, but only supports initializing a newly-allocated
3470b57cec5SDimitry Andric   /// SDUse with a non-null value.
3480b57cec5SDimitry Andric   inline void setInitial(const SDValue &V);
3490b57cec5SDimitry Andric   /// Like set, but only sets the Node portion of the value,
3500b57cec5SDimitry Andric   /// leaving the ResNo portion unmodified.
3510b57cec5SDimitry Andric   inline void setNode(SDNode *N);
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   void addToList(SDUse **List) {
3540b57cec5SDimitry Andric     Next = *List;
3550b57cec5SDimitry Andric     if (Next) Next->Prev = &Next;
3560b57cec5SDimitry Andric     Prev = List;
3570b57cec5SDimitry Andric     *List = this;
3580b57cec5SDimitry Andric   }
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric   void removeFromList() {
3610b57cec5SDimitry Andric     *Prev = Next;
3620b57cec5SDimitry Andric     if (Next) Next->Prev = Prev;
3630b57cec5SDimitry Andric   }
3640b57cec5SDimitry Andric };
3650b57cec5SDimitry Andric 
3660b57cec5SDimitry Andric /// simplify_type specializations - Allow casting operators to work directly on
3670b57cec5SDimitry Andric /// SDValues as if they were SDNode*'s.
3680b57cec5SDimitry Andric template<> struct simplify_type<SDUse> {
3690b57cec5SDimitry Andric   using SimpleType = SDNode *;
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric   static SimpleType getSimplifiedValue(SDUse &Val) {
3720b57cec5SDimitry Andric     return Val.getNode();
3730b57cec5SDimitry Andric   }
3740b57cec5SDimitry Andric };
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric /// These are IR-level optimization flags that may be propagated to SDNodes.
3770b57cec5SDimitry Andric /// TODO: This data structure should be shared by the IR optimizer and the
3780b57cec5SDimitry Andric /// the backend.
3790b57cec5SDimitry Andric struct SDNodeFlags {
3800b57cec5SDimitry Andric private:
3810b57cec5SDimitry Andric   bool NoUnsignedWrap : 1;
3820b57cec5SDimitry Andric   bool NoSignedWrap : 1;
3830b57cec5SDimitry Andric   bool Exact : 1;
3841db9f3b2SDimitry Andric   bool Disjoint : 1;
3855f757f3fSDimitry Andric   bool NonNeg : 1;
3860b57cec5SDimitry Andric   bool NoNaNs : 1;
3870b57cec5SDimitry Andric   bool NoInfs : 1;
3880b57cec5SDimitry Andric   bool NoSignedZeros : 1;
3890b57cec5SDimitry Andric   bool AllowReciprocal : 1;
3900b57cec5SDimitry Andric   bool AllowContract : 1;
3910b57cec5SDimitry Andric   bool ApproximateFuncs : 1;
3920b57cec5SDimitry Andric   bool AllowReassociation : 1;
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric   // We assume instructions do not raise floating-point exceptions by default,
3950b57cec5SDimitry Andric   // and only those marked explicitly may do so.  We could choose to represent
3960b57cec5SDimitry Andric   // this via a positive "FPExcept" flags like on the MI level, but having a
39706c3fb27SDimitry Andric   // negative "NoFPExcept" flag here makes the flag intersection logic more
39806c3fb27SDimitry Andric   // straightforward.
3990b57cec5SDimitry Andric   bool NoFPExcept : 1;
40006c3fb27SDimitry Andric   // Instructions with attached 'unpredictable' metadata on IR level.
40106c3fb27SDimitry Andric   bool Unpredictable : 1;
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric public:
4040b57cec5SDimitry Andric   /// Default constructor turns off all optimization flags.
4050b57cec5SDimitry Andric   SDNodeFlags()
4061db9f3b2SDimitry Andric       : NoUnsignedWrap(false), NoSignedWrap(false), Exact(false),
4071db9f3b2SDimitry Andric         Disjoint(false), NonNeg(false), NoNaNs(false), NoInfs(false),
4081db9f3b2SDimitry Andric         NoSignedZeros(false), AllowReciprocal(false), AllowContract(false),
4091db9f3b2SDimitry Andric         ApproximateFuncs(false), AllowReassociation(false), NoFPExcept(false),
4101db9f3b2SDimitry Andric         Unpredictable(false) {}
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric   /// Propagate the fast-math-flags from an IR FPMathOperator.
4130b57cec5SDimitry Andric   void copyFMF(const FPMathOperator &FPMO) {
4140b57cec5SDimitry Andric     setNoNaNs(FPMO.hasNoNaNs());
4150b57cec5SDimitry Andric     setNoInfs(FPMO.hasNoInfs());
4160b57cec5SDimitry Andric     setNoSignedZeros(FPMO.hasNoSignedZeros());
4170b57cec5SDimitry Andric     setAllowReciprocal(FPMO.hasAllowReciprocal());
4180b57cec5SDimitry Andric     setAllowContract(FPMO.hasAllowContract());
4190b57cec5SDimitry Andric     setApproximateFuncs(FPMO.hasApproxFunc());
4200b57cec5SDimitry Andric     setAllowReassociation(FPMO.hasAllowReassoc());
4210b57cec5SDimitry Andric   }
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric   // These are mutators for each flag.
424e8d8bef9SDimitry Andric   void setNoUnsignedWrap(bool b) { NoUnsignedWrap = b; }
425e8d8bef9SDimitry Andric   void setNoSignedWrap(bool b) { NoSignedWrap = b; }
426e8d8bef9SDimitry Andric   void setExact(bool b) { Exact = b; }
4271db9f3b2SDimitry Andric   void setDisjoint(bool b) { Disjoint = b; }
4285f757f3fSDimitry Andric   void setNonNeg(bool b) { NonNeg = b; }
429e8d8bef9SDimitry Andric   void setNoNaNs(bool b) { NoNaNs = b; }
430e8d8bef9SDimitry Andric   void setNoInfs(bool b) { NoInfs = b; }
431e8d8bef9SDimitry Andric   void setNoSignedZeros(bool b) { NoSignedZeros = b; }
432e8d8bef9SDimitry Andric   void setAllowReciprocal(bool b) { AllowReciprocal = b; }
433e8d8bef9SDimitry Andric   void setAllowContract(bool b) { AllowContract = b; }
434e8d8bef9SDimitry Andric   void setApproximateFuncs(bool b) { ApproximateFuncs = b; }
435e8d8bef9SDimitry Andric   void setAllowReassociation(bool b) { AllowReassociation = b; }
436e8d8bef9SDimitry Andric   void setNoFPExcept(bool b) { NoFPExcept = b; }
43706c3fb27SDimitry Andric   void setUnpredictable(bool b) { Unpredictable = b; }
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   // These are accessors for each flag.
4400b57cec5SDimitry Andric   bool hasNoUnsignedWrap() const { return NoUnsignedWrap; }
4410b57cec5SDimitry Andric   bool hasNoSignedWrap() const { return NoSignedWrap; }
4420b57cec5SDimitry Andric   bool hasExact() const { return Exact; }
4431db9f3b2SDimitry Andric   bool hasDisjoint() const { return Disjoint; }
4445f757f3fSDimitry Andric   bool hasNonNeg() const { return NonNeg; }
4450b57cec5SDimitry Andric   bool hasNoNaNs() const { return NoNaNs; }
4460b57cec5SDimitry Andric   bool hasNoInfs() const { return NoInfs; }
4470b57cec5SDimitry Andric   bool hasNoSignedZeros() const { return NoSignedZeros; }
4480b57cec5SDimitry Andric   bool hasAllowReciprocal() const { return AllowReciprocal; }
4490b57cec5SDimitry Andric   bool hasAllowContract() const { return AllowContract; }
4500b57cec5SDimitry Andric   bool hasApproximateFuncs() const { return ApproximateFuncs; }
4510b57cec5SDimitry Andric   bool hasAllowReassociation() const { return AllowReassociation; }
452480093f4SDimitry Andric   bool hasNoFPExcept() const { return NoFPExcept; }
45306c3fb27SDimitry Andric   bool hasUnpredictable() const { return Unpredictable; }
4540b57cec5SDimitry Andric 
455e8d8bef9SDimitry Andric   /// Clear any flags in this flag set that aren't also set in Flags. All
456e8d8bef9SDimitry Andric   /// flags will be cleared if Flags are undefined.
4570b57cec5SDimitry Andric   void intersectWith(const SDNodeFlags Flags) {
4580b57cec5SDimitry Andric     NoUnsignedWrap &= Flags.NoUnsignedWrap;
4590b57cec5SDimitry Andric     NoSignedWrap &= Flags.NoSignedWrap;
4600b57cec5SDimitry Andric     Exact &= Flags.Exact;
4611db9f3b2SDimitry Andric     Disjoint &= Flags.Disjoint;
4625f757f3fSDimitry Andric     NonNeg &= Flags.NonNeg;
4630b57cec5SDimitry Andric     NoNaNs &= Flags.NoNaNs;
4640b57cec5SDimitry Andric     NoInfs &= Flags.NoInfs;
4650b57cec5SDimitry Andric     NoSignedZeros &= Flags.NoSignedZeros;
4660b57cec5SDimitry Andric     AllowReciprocal &= Flags.AllowReciprocal;
4670b57cec5SDimitry Andric     AllowContract &= Flags.AllowContract;
4680b57cec5SDimitry Andric     ApproximateFuncs &= Flags.ApproximateFuncs;
4690b57cec5SDimitry Andric     AllowReassociation &= Flags.AllowReassociation;
4700b57cec5SDimitry Andric     NoFPExcept &= Flags.NoFPExcept;
47106c3fb27SDimitry Andric     Unpredictable &= Flags.Unpredictable;
4720b57cec5SDimitry Andric   }
4730b57cec5SDimitry Andric };
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric /// Represents one node in the SelectionDAG.
4760b57cec5SDimitry Andric ///
4770b57cec5SDimitry Andric class SDNode : public FoldingSetNode, public ilist_node<SDNode> {
4780b57cec5SDimitry Andric private:
4790b57cec5SDimitry Andric   /// The operation that this node performs.
480bdd1243dSDimitry Andric   int32_t NodeType;
481bdd1243dSDimitry Andric 
482*0fca6ea1SDimitry Andric   SDNodeFlags Flags;
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric protected:
4850b57cec5SDimitry Andric   // We define a set of mini-helper classes to help us interpret the bits in our
4860b57cec5SDimitry Andric   // SubclassData.  These are designed to fit within a uint16_t so they pack
487*0fca6ea1SDimitry Andric   // with SDNodeFlags.
4880b57cec5SDimitry Andric 
489fe6060f1SDimitry Andric #if defined(_AIX) && (!defined(__GNUC__) || defined(__clang__))
4900b57cec5SDimitry Andric // Except for GCC; by default, AIX compilers store bit-fields in 4-byte words
4910b57cec5SDimitry Andric // and give the `pack` pragma push semantics.
4920b57cec5SDimitry Andric #define BEGIN_TWO_BYTE_PACK() _Pragma("pack(2)")
4930b57cec5SDimitry Andric #define END_TWO_BYTE_PACK() _Pragma("pack(pop)")
4940b57cec5SDimitry Andric #else
4950b57cec5SDimitry Andric #define BEGIN_TWO_BYTE_PACK()
4960b57cec5SDimitry Andric #define END_TWO_BYTE_PACK()
4970b57cec5SDimitry Andric #endif
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric BEGIN_TWO_BYTE_PACK()
5000b57cec5SDimitry Andric   class SDNodeBitfields {
5010b57cec5SDimitry Andric     friend class SDNode;
5020b57cec5SDimitry Andric     friend class MemIntrinsicSDNode;
5030b57cec5SDimitry Andric     friend class MemSDNode;
5040b57cec5SDimitry Andric     friend class SelectionDAG;
5050b57cec5SDimitry Andric 
5060b57cec5SDimitry Andric     uint16_t HasDebugValue : 1;
5070b57cec5SDimitry Andric     uint16_t IsMemIntrinsic : 1;
5080b57cec5SDimitry Andric     uint16_t IsDivergent : 1;
5090b57cec5SDimitry Andric   };
5100b57cec5SDimitry Andric   enum { NumSDNodeBits = 3 };
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric   class ConstantSDNodeBitfields {
5130b57cec5SDimitry Andric     friend class ConstantSDNode;
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric     uint16_t : NumSDNodeBits;
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric     uint16_t IsOpaque : 1;
5180b57cec5SDimitry Andric   };
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric   class MemSDNodeBitfields {
5210b57cec5SDimitry Andric     friend class MemSDNode;
5220b57cec5SDimitry Andric     friend class MemIntrinsicSDNode;
5230b57cec5SDimitry Andric     friend class AtomicSDNode;
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric     uint16_t : NumSDNodeBits;
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric     uint16_t IsVolatile : 1;
5280b57cec5SDimitry Andric     uint16_t IsNonTemporal : 1;
5290b57cec5SDimitry Andric     uint16_t IsDereferenceable : 1;
5300b57cec5SDimitry Andric     uint16_t IsInvariant : 1;
5310b57cec5SDimitry Andric   };
5320b57cec5SDimitry Andric   enum { NumMemSDNodeBits = NumSDNodeBits + 4 };
5330b57cec5SDimitry Andric 
5340b57cec5SDimitry Andric   class LSBaseSDNodeBitfields {
5350b57cec5SDimitry Andric     friend class LSBaseSDNode;
53681ad6265SDimitry Andric     friend class VPBaseLoadStoreSDNode;
537480093f4SDimitry Andric     friend class MaskedLoadStoreSDNode;
5388bcb0991SDimitry Andric     friend class MaskedGatherScatterSDNode;
539349cc55cSDimitry Andric     friend class VPGatherScatterSDNode;
540*0fca6ea1SDimitry Andric     friend class MaskedHistogramSDNode;
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric     uint16_t : NumMemSDNodeBits;
5430b57cec5SDimitry Andric 
5448bcb0991SDimitry Andric     // This storage is shared between disparate class hierarchies to hold an
5458bcb0991SDimitry Andric     // enumeration specific to the class hierarchy in use.
5468bcb0991SDimitry Andric     //   LSBaseSDNode => enum ISD::MemIndexedMode
547349cc55cSDimitry Andric     //   VPLoadStoreBaseSDNode => enum ISD::MemIndexedMode
548480093f4SDimitry Andric     //   MaskedLoadStoreBaseSDNode => enum ISD::MemIndexedMode
549349cc55cSDimitry Andric     //   VPGatherScatterSDNode => enum ISD::MemIndexType
5508bcb0991SDimitry Andric     //   MaskedGatherScatterSDNode => enum ISD::MemIndexType
551*0fca6ea1SDimitry Andric     //   MaskedHistogramSDNode => enum ISD::MemIndexType
5528bcb0991SDimitry Andric     uint16_t AddressingMode : 3;
5530b57cec5SDimitry Andric   };
5540b57cec5SDimitry Andric   enum { NumLSBaseSDNodeBits = NumMemSDNodeBits + 3 };
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric   class LoadSDNodeBitfields {
5570b57cec5SDimitry Andric     friend class LoadSDNode;
558*0fca6ea1SDimitry Andric     friend class AtomicSDNode;
559349cc55cSDimitry Andric     friend class VPLoadSDNode;
56081ad6265SDimitry Andric     friend class VPStridedLoadSDNode;
5610b57cec5SDimitry Andric     friend class MaskedLoadSDNode;
562e8d8bef9SDimitry Andric     friend class MaskedGatherSDNode;
563349cc55cSDimitry Andric     friend class VPGatherSDNode;
564*0fca6ea1SDimitry Andric     friend class MaskedHistogramSDNode;
5650b57cec5SDimitry Andric 
5660b57cec5SDimitry Andric     uint16_t : NumLSBaseSDNodeBits;
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric     uint16_t ExtTy : 2; // enum ISD::LoadExtType
5690b57cec5SDimitry Andric     uint16_t IsExpanding : 1;
5700b57cec5SDimitry Andric   };
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric   class StoreSDNodeBitfields {
5730b57cec5SDimitry Andric     friend class StoreSDNode;
574349cc55cSDimitry Andric     friend class VPStoreSDNode;
57581ad6265SDimitry Andric     friend class VPStridedStoreSDNode;
5760b57cec5SDimitry Andric     friend class MaskedStoreSDNode;
577e8d8bef9SDimitry Andric     friend class MaskedScatterSDNode;
578349cc55cSDimitry Andric     friend class VPScatterSDNode;
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric     uint16_t : NumLSBaseSDNodeBits;
5810b57cec5SDimitry Andric 
5820b57cec5SDimitry Andric     uint16_t IsTruncating : 1;
5830b57cec5SDimitry Andric     uint16_t IsCompressing : 1;
5840b57cec5SDimitry Andric   };
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric   union {
5870b57cec5SDimitry Andric     char RawSDNodeBits[sizeof(uint16_t)];
5880b57cec5SDimitry Andric     SDNodeBitfields SDNodeBits;
5890b57cec5SDimitry Andric     ConstantSDNodeBitfields ConstantSDNodeBits;
5900b57cec5SDimitry Andric     MemSDNodeBitfields MemSDNodeBits;
5910b57cec5SDimitry Andric     LSBaseSDNodeBitfields LSBaseSDNodeBits;
5920b57cec5SDimitry Andric     LoadSDNodeBitfields LoadSDNodeBits;
5930b57cec5SDimitry Andric     StoreSDNodeBitfields StoreSDNodeBits;
5940b57cec5SDimitry Andric   };
5950b57cec5SDimitry Andric END_TWO_BYTE_PACK()
5960b57cec5SDimitry Andric #undef BEGIN_TWO_BYTE_PACK
5970b57cec5SDimitry Andric #undef END_TWO_BYTE_PACK
5980b57cec5SDimitry Andric 
5990b57cec5SDimitry Andric   // RawSDNodeBits must cover the entirety of the union.  This means that all of
6000b57cec5SDimitry Andric   // the union's members must have size <= RawSDNodeBits.  We write the RHS as
6010b57cec5SDimitry Andric   // "2" instead of sizeof(RawSDNodeBits) because MSVC can't handle the latter.
6020b57cec5SDimitry Andric   static_assert(sizeof(SDNodeBitfields) <= 2, "field too wide");
6030b57cec5SDimitry Andric   static_assert(sizeof(ConstantSDNodeBitfields) <= 2, "field too wide");
6040b57cec5SDimitry Andric   static_assert(sizeof(MemSDNodeBitfields) <= 2, "field too wide");
6050b57cec5SDimitry Andric   static_assert(sizeof(LSBaseSDNodeBitfields) <= 2, "field too wide");
6060b57cec5SDimitry Andric   static_assert(sizeof(LoadSDNodeBitfields) <= 2, "field too wide");
6070b57cec5SDimitry Andric   static_assert(sizeof(StoreSDNodeBitfields) <= 2, "field too wide");
6080b57cec5SDimitry Andric 
609*0fca6ea1SDimitry Andric public:
610*0fca6ea1SDimitry Andric   /// Unique and persistent id per SDNode in the DAG. Used for debug printing.
611*0fca6ea1SDimitry Andric   /// We do not place that under `#if LLVM_ENABLE_ABI_BREAKING_CHECKS`
612*0fca6ea1SDimitry Andric   /// intentionally because it adds unneeded complexity without noticeable
613*0fca6ea1SDimitry Andric   /// benefits (see discussion with @thakis in D120714). Currently, there are
614*0fca6ea1SDimitry Andric   /// two padding bytes after this field.
615*0fca6ea1SDimitry Andric   uint16_t PersistentId = 0xffff;
616*0fca6ea1SDimitry Andric 
6170b57cec5SDimitry Andric private:
6180b57cec5SDimitry Andric   friend class SelectionDAG;
6190b57cec5SDimitry Andric   // TODO: unfriend HandleSDNode once we fix its operand handling.
6200b57cec5SDimitry Andric   friend class HandleSDNode;
6210b57cec5SDimitry Andric 
6220b57cec5SDimitry Andric   /// Unique id per SDNode in the DAG.
6230b57cec5SDimitry Andric   int NodeId = -1;
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric   /// The values that are used by this operation.
6260b57cec5SDimitry Andric   SDUse *OperandList = nullptr;
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric   /// The types of the values this node defines.  SDNode's may
6290b57cec5SDimitry Andric   /// define multiple values simultaneously.
6300b57cec5SDimitry Andric   const EVT *ValueList;
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric   /// List of uses for this SDNode.
6330b57cec5SDimitry Andric   SDUse *UseList = nullptr;
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric   /// The number of entries in the Operand/Value list.
6360b57cec5SDimitry Andric   unsigned short NumOperands = 0;
6370b57cec5SDimitry Andric   unsigned short NumValues;
6380b57cec5SDimitry Andric 
6390b57cec5SDimitry Andric   // The ordering of the SDNodes. It roughly corresponds to the ordering of the
6400b57cec5SDimitry Andric   // original LLVM instructions.
6410b57cec5SDimitry Andric   // This is used for turning off scheduling, because we'll forgo
6420b57cec5SDimitry Andric   // the normal scheduling algorithms and output the instructions according to
6430b57cec5SDimitry Andric   // this ordering.
6440b57cec5SDimitry Andric   unsigned IROrder;
6450b57cec5SDimitry Andric 
6460b57cec5SDimitry Andric   /// Source line information.
6470b57cec5SDimitry Andric   DebugLoc debugLoc;
6480b57cec5SDimitry Andric 
6490b57cec5SDimitry Andric   /// Return a pointer to the specified value type.
6500b57cec5SDimitry Andric   static const EVT *getValueTypeList(EVT VT);
6510b57cec5SDimitry Andric 
652*0fca6ea1SDimitry Andric   /// Index in worklist of DAGCombiner, or negative if the node is not in the
653*0fca6ea1SDimitry Andric   /// worklist. -1 = not in worklist; -2 = not in worklist, but has already been
654*0fca6ea1SDimitry Andric   /// combined at least once.
655*0fca6ea1SDimitry Andric   int CombinerWorklistIndex = -1;
6560b57cec5SDimitry Andric 
657bdd1243dSDimitry Andric   uint32_t CFIType = 0;
6580b57cec5SDimitry Andric 
659bdd1243dSDimitry Andric public:
6600b57cec5SDimitry Andric   //===--------------------------------------------------------------------===//
6610b57cec5SDimitry Andric   //  Accessors
6620b57cec5SDimitry Andric   //
6630b57cec5SDimitry Andric 
6640b57cec5SDimitry Andric   /// Return the SelectionDAG opcode value for this node. For
6650b57cec5SDimitry Andric   /// pre-isel nodes (those for which isMachineOpcode returns false), these
6660b57cec5SDimitry Andric   /// are the opcode values in the ISD and <target>ISD namespaces. For
6670b57cec5SDimitry Andric   /// post-isel opcodes, see getMachineOpcode.
668bdd1243dSDimitry Andric   unsigned getOpcode()  const { return (unsigned)NodeType; }
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric   /// Test if this node has a target-specific opcode (in the
6710b57cec5SDimitry Andric   /// \<target\>ISD namespace).
6720b57cec5SDimitry Andric   bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; }
6730b57cec5SDimitry Andric 
674480093f4SDimitry Andric   /// Test if this node has a target-specific opcode that may raise
675480093f4SDimitry Andric   /// FP exceptions (in the \<target\>ISD namespace and greater than
676480093f4SDimitry Andric   /// FIRST_TARGET_STRICTFP_OPCODE).  Note that all target memory
677480093f4SDimitry Andric   /// opcode are currently automatically considered to possibly raise
678480093f4SDimitry Andric   /// FP exceptions as well.
679480093f4SDimitry Andric   bool isTargetStrictFPOpcode() const {
680480093f4SDimitry Andric     return NodeType >= ISD::FIRST_TARGET_STRICTFP_OPCODE;
681480093f4SDimitry Andric   }
682480093f4SDimitry Andric 
6830b57cec5SDimitry Andric   /// Test if this node has a target-specific
6840b57cec5SDimitry Andric   /// memory-referencing opcode (in the \<target\>ISD namespace and
6850b57cec5SDimitry Andric   /// greater than FIRST_TARGET_MEMORY_OPCODE).
6860b57cec5SDimitry Andric   bool isTargetMemoryOpcode() const {
6870b57cec5SDimitry Andric     return NodeType >= ISD::FIRST_TARGET_MEMORY_OPCODE;
6880b57cec5SDimitry Andric   }
6890b57cec5SDimitry Andric 
6900b57cec5SDimitry Andric   /// Return true if the type of the node type undefined.
6910b57cec5SDimitry Andric   bool isUndef() const { return NodeType == ISD::UNDEF; }
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric   /// Test if this node is a memory intrinsic (with valid pointer information).
6940b57cec5SDimitry Andric   /// INTRINSIC_W_CHAIN and INTRINSIC_VOID nodes are sometimes created for
6950b57cec5SDimitry Andric   /// non-memory intrinsics (with chains) that are not really instances of
6960b57cec5SDimitry Andric   /// MemSDNode. For such nodes, we need some extra state to determine the
6970b57cec5SDimitry Andric   /// proper classof relationship.
6980b57cec5SDimitry Andric   bool isMemIntrinsic() const {
6990b57cec5SDimitry Andric     return (NodeType == ISD::INTRINSIC_W_CHAIN ||
7000b57cec5SDimitry Andric             NodeType == ISD::INTRINSIC_VOID) &&
7010b57cec5SDimitry Andric            SDNodeBits.IsMemIntrinsic;
7020b57cec5SDimitry Andric   }
7030b57cec5SDimitry Andric 
7040b57cec5SDimitry Andric   /// Test if this node is a strict floating point pseudo-op.
7050b57cec5SDimitry Andric   bool isStrictFPOpcode() {
7060b57cec5SDimitry Andric     switch (NodeType) {
7070b57cec5SDimitry Andric       default:
7080b57cec5SDimitry Andric         return false;
7095ffd83dbSDimitry Andric       case ISD::STRICT_FP16_TO_FP:
7105ffd83dbSDimitry Andric       case ISD::STRICT_FP_TO_FP16:
711*0fca6ea1SDimitry Andric       case ISD::STRICT_BF16_TO_FP:
712*0fca6ea1SDimitry Andric       case ISD::STRICT_FP_TO_BF16:
7135ffd83dbSDimitry Andric #define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)               \
714480093f4SDimitry Andric       case ISD::STRICT_##DAGN:
715480093f4SDimitry Andric #include "llvm/IR/ConstrainedOps.def"
7160b57cec5SDimitry Andric         return true;
7170b57cec5SDimitry Andric     }
7180b57cec5SDimitry Andric   }
7190b57cec5SDimitry Andric 
72004eeddc0SDimitry Andric   /// Test if this node is a vector predication operation.
72104eeddc0SDimitry Andric   bool isVPOpcode() const { return ISD::isVPOpcode(getOpcode()); }
72204eeddc0SDimitry Andric 
7230b57cec5SDimitry Andric   /// Test if this node has a post-isel opcode, directly
7240b57cec5SDimitry Andric   /// corresponding to a MachineInstr opcode.
7250b57cec5SDimitry Andric   bool isMachineOpcode() const { return NodeType < 0; }
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric   /// This may only be called if isMachineOpcode returns
7280b57cec5SDimitry Andric   /// true. It returns the MachineInstr opcode value that the node's opcode
7290b57cec5SDimitry Andric   /// corresponds to.
7300b57cec5SDimitry Andric   unsigned getMachineOpcode() const {
7310b57cec5SDimitry Andric     assert(isMachineOpcode() && "Not a MachineInstr opcode!");
7320b57cec5SDimitry Andric     return ~NodeType;
7330b57cec5SDimitry Andric   }
7340b57cec5SDimitry Andric 
7350b57cec5SDimitry Andric   bool getHasDebugValue() const { return SDNodeBits.HasDebugValue; }
7360b57cec5SDimitry Andric   void setHasDebugValue(bool b) { SDNodeBits.HasDebugValue = b; }
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric   bool isDivergent() const { return SDNodeBits.IsDivergent; }
7390b57cec5SDimitry Andric 
7400b57cec5SDimitry Andric   /// Return true if there are no uses of this node.
7410b57cec5SDimitry Andric   bool use_empty() const { return UseList == nullptr; }
7420b57cec5SDimitry Andric 
7430b57cec5SDimitry Andric   /// Return true if there is exactly one use of this node.
744e8d8bef9SDimitry Andric   bool hasOneUse() const { return hasSingleElement(uses()); }
7450b57cec5SDimitry Andric 
7460b57cec5SDimitry Andric   /// Return the number of uses of this node. This method takes
7470b57cec5SDimitry Andric   /// time proportional to the number of uses.
7480b57cec5SDimitry Andric   size_t use_size() const { return std::distance(use_begin(), use_end()); }
7490b57cec5SDimitry Andric 
7500b57cec5SDimitry Andric   /// Return the unique node id.
7510b57cec5SDimitry Andric   int getNodeId() const { return NodeId; }
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric   /// Set unique node id.
7540b57cec5SDimitry Andric   void setNodeId(int Id) { NodeId = Id; }
7550b57cec5SDimitry Andric 
756*0fca6ea1SDimitry Andric   /// Get worklist index for DAGCombiner
757*0fca6ea1SDimitry Andric   int getCombinerWorklistIndex() const { return CombinerWorklistIndex; }
758*0fca6ea1SDimitry Andric 
759*0fca6ea1SDimitry Andric   /// Set worklist index for DAGCombiner
760*0fca6ea1SDimitry Andric   void setCombinerWorklistIndex(int Index) { CombinerWorklistIndex = Index; }
761*0fca6ea1SDimitry Andric 
7620b57cec5SDimitry Andric   /// Return the node ordering.
7630b57cec5SDimitry Andric   unsigned getIROrder() const { return IROrder; }
7640b57cec5SDimitry Andric 
7650b57cec5SDimitry Andric   /// Set the node ordering.
7660b57cec5SDimitry Andric   void setIROrder(unsigned Order) { IROrder = Order; }
7670b57cec5SDimitry Andric 
7680b57cec5SDimitry Andric   /// Return the source location info.
7690b57cec5SDimitry Andric   const DebugLoc &getDebugLoc() const { return debugLoc; }
7700b57cec5SDimitry Andric 
7710b57cec5SDimitry Andric   /// Set source location info.  Try to avoid this, putting
7720b57cec5SDimitry Andric   /// it in the constructor is preferable.
7730b57cec5SDimitry Andric   void setDebugLoc(DebugLoc dl) { debugLoc = std::move(dl); }
7740b57cec5SDimitry Andric 
7750b57cec5SDimitry Andric   /// This class provides iterator support for SDUse
7760b57cec5SDimitry Andric   /// operands that use a specific SDNode.
777fe6060f1SDimitry Andric   class use_iterator {
7780b57cec5SDimitry Andric     friend class SDNode;
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric     SDUse *Op = nullptr;
7810b57cec5SDimitry Andric 
7820b57cec5SDimitry Andric     explicit use_iterator(SDUse *op) : Op(op) {}
7830b57cec5SDimitry Andric 
7840b57cec5SDimitry Andric   public:
785fe6060f1SDimitry Andric     using iterator_category = std::forward_iterator_tag;
786fe6060f1SDimitry Andric     using value_type = SDUse;
787fe6060f1SDimitry Andric     using difference_type = std::ptrdiff_t;
788fe6060f1SDimitry Andric     using pointer = value_type *;
789fe6060f1SDimitry Andric     using reference = value_type &;
7900b57cec5SDimitry Andric 
7910b57cec5SDimitry Andric     use_iterator() = default;
7921fd87a68SDimitry Andric     use_iterator(const use_iterator &I) = default;
793bdd1243dSDimitry Andric     use_iterator &operator=(const use_iterator &) = default;
7940b57cec5SDimitry Andric 
7951fd87a68SDimitry Andric     bool operator==(const use_iterator &x) const { return Op == x.Op; }
7960b57cec5SDimitry Andric     bool operator!=(const use_iterator &x) const {
7970b57cec5SDimitry Andric       return !operator==(x);
7980b57cec5SDimitry Andric     }
7990b57cec5SDimitry Andric 
8000b57cec5SDimitry Andric     /// Return true if this iterator is at the end of uses list.
8010b57cec5SDimitry Andric     bool atEnd() const { return Op == nullptr; }
8020b57cec5SDimitry Andric 
8030b57cec5SDimitry Andric     // Iterator traversal: forward iteration only.
8040b57cec5SDimitry Andric     use_iterator &operator++() {          // Preincrement
8050b57cec5SDimitry Andric       assert(Op && "Cannot increment end iterator!");
8060b57cec5SDimitry Andric       Op = Op->getNext();
8070b57cec5SDimitry Andric       return *this;
8080b57cec5SDimitry Andric     }
8090b57cec5SDimitry Andric 
8100b57cec5SDimitry Andric     use_iterator operator++(int) {        // Postincrement
8110b57cec5SDimitry Andric       use_iterator tmp = *this; ++*this; return tmp;
8120b57cec5SDimitry Andric     }
8130b57cec5SDimitry Andric 
8140b57cec5SDimitry Andric     /// Retrieve a pointer to the current user node.
8150b57cec5SDimitry Andric     SDNode *operator*() const {
8160b57cec5SDimitry Andric       assert(Op && "Cannot dereference end iterator!");
8170b57cec5SDimitry Andric       return Op->getUser();
8180b57cec5SDimitry Andric     }
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric     SDNode *operator->() const { return operator*(); }
8210b57cec5SDimitry Andric 
8220b57cec5SDimitry Andric     SDUse &getUse() const { return *Op; }
8230b57cec5SDimitry Andric 
8240b57cec5SDimitry Andric     /// Retrieve the operand # of this use in its user.
8250b57cec5SDimitry Andric     unsigned getOperandNo() const {
8260b57cec5SDimitry Andric       assert(Op && "Cannot dereference end iterator!");
8270b57cec5SDimitry Andric       return (unsigned)(Op - Op->getUser()->OperandList);
8280b57cec5SDimitry Andric     }
8290b57cec5SDimitry Andric   };
8300b57cec5SDimitry Andric 
8310b57cec5SDimitry Andric   /// Provide iteration support to walk over all uses of an SDNode.
8320b57cec5SDimitry Andric   use_iterator use_begin() const {
8330b57cec5SDimitry Andric     return use_iterator(UseList);
8340b57cec5SDimitry Andric   }
8350b57cec5SDimitry Andric 
8360b57cec5SDimitry Andric   static use_iterator use_end() { return use_iterator(nullptr); }
8370b57cec5SDimitry Andric 
8380b57cec5SDimitry Andric   inline iterator_range<use_iterator> uses() {
8390b57cec5SDimitry Andric     return make_range(use_begin(), use_end());
8400b57cec5SDimitry Andric   }
8410b57cec5SDimitry Andric   inline iterator_range<use_iterator> uses() const {
8420b57cec5SDimitry Andric     return make_range(use_begin(), use_end());
8430b57cec5SDimitry Andric   }
8440b57cec5SDimitry Andric 
8450b57cec5SDimitry Andric   /// Return true if there are exactly NUSES uses of the indicated value.
8460b57cec5SDimitry Andric   /// This method ignores uses of other values defined by this operation.
8470b57cec5SDimitry Andric   bool hasNUsesOfValue(unsigned NUses, unsigned Value) const;
8480b57cec5SDimitry Andric 
8490b57cec5SDimitry Andric   /// Return true if there are any use of the indicated value.
8500b57cec5SDimitry Andric   /// This method ignores uses of other values defined by this operation.
8510b57cec5SDimitry Andric   bool hasAnyUseOfValue(unsigned Value) const;
8520b57cec5SDimitry Andric 
8530b57cec5SDimitry Andric   /// Return true if this node is the only use of N.
8540b57cec5SDimitry Andric   bool isOnlyUserOf(const SDNode *N) const;
8550b57cec5SDimitry Andric 
8560b57cec5SDimitry Andric   /// Return true if this node is an operand of N.
8570b57cec5SDimitry Andric   bool isOperandOf(const SDNode *N) const;
8580b57cec5SDimitry Andric 
8590b57cec5SDimitry Andric   /// Return true if this node is a predecessor of N.
8600b57cec5SDimitry Andric   /// NOTE: Implemented on top of hasPredecessor and every bit as
8610b57cec5SDimitry Andric   /// expensive. Use carefully.
8620b57cec5SDimitry Andric   bool isPredecessorOf(const SDNode *N) const {
8630b57cec5SDimitry Andric     return N->hasPredecessor(this);
8640b57cec5SDimitry Andric   }
8650b57cec5SDimitry Andric 
8660b57cec5SDimitry Andric   /// Return true if N is a predecessor of this node.
8670b57cec5SDimitry Andric   /// N is either an operand of this node, or can be reached by recursively
8680b57cec5SDimitry Andric   /// traversing up the operands.
8690b57cec5SDimitry Andric   /// NOTE: This is an expensive method. Use it carefully.
8700b57cec5SDimitry Andric   bool hasPredecessor(const SDNode *N) const;
8710b57cec5SDimitry Andric 
8720b57cec5SDimitry Andric   /// Returns true if N is a predecessor of any node in Worklist. This
8730b57cec5SDimitry Andric   /// helper keeps Visited and Worklist sets externally to allow unions
8740b57cec5SDimitry Andric   /// searches to be performed in parallel, caching of results across
8750b57cec5SDimitry Andric   /// queries and incremental addition to Worklist. Stops early if N is
8760b57cec5SDimitry Andric   /// found but will resume. Remember to clear Visited and Worklists
8770b57cec5SDimitry Andric   /// if DAG changes. MaxSteps gives a maximum number of nodes to visit before
8780b57cec5SDimitry Andric   /// giving up. The TopologicalPrune flag signals that positive NodeIds are
8790b57cec5SDimitry Andric   /// topologically ordered (Operands have strictly smaller node id) and search
8800b57cec5SDimitry Andric   /// can be pruned leveraging this.
8810b57cec5SDimitry Andric   static bool hasPredecessorHelper(const SDNode *N,
8820b57cec5SDimitry Andric                                    SmallPtrSetImpl<const SDNode *> &Visited,
8830b57cec5SDimitry Andric                                    SmallVectorImpl<const SDNode *> &Worklist,
8840b57cec5SDimitry Andric                                    unsigned int MaxSteps = 0,
8850b57cec5SDimitry Andric                                    bool TopologicalPrune = false) {
8860b57cec5SDimitry Andric     SmallVector<const SDNode *, 8> DeferredNodes;
8870b57cec5SDimitry Andric     if (Visited.count(N))
8880b57cec5SDimitry Andric       return true;
8890b57cec5SDimitry Andric 
8900b57cec5SDimitry Andric     // Node Id's are assigned in three places: As a topological
8910b57cec5SDimitry Andric     // ordering (> 0), during legalization (results in values set to
8920b57cec5SDimitry Andric     // 0), new nodes (set to -1). If N has a topolgical id then we
8930b57cec5SDimitry Andric     // know that all nodes with ids smaller than it cannot be
8940b57cec5SDimitry Andric     // successors and we need not check them. Filter out all node
8950b57cec5SDimitry Andric     // that can't be matches. We add them to the worklist before exit
8960b57cec5SDimitry Andric     // in case of multiple calls. Note that during selection the topological id
8970b57cec5SDimitry Andric     // may be violated if a node's predecessor is selected before it. We mark
8980b57cec5SDimitry Andric     // this at selection negating the id of unselected successors and
8990b57cec5SDimitry Andric     // restricting topological pruning to positive ids.
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric     int NId = N->getNodeId();
9020b57cec5SDimitry Andric     // If we Invalidated the Id, reconstruct original NId.
9030b57cec5SDimitry Andric     if (NId < -1)
9040b57cec5SDimitry Andric       NId = -(NId + 1);
9050b57cec5SDimitry Andric 
9060b57cec5SDimitry Andric     bool Found = false;
9070b57cec5SDimitry Andric     while (!Worklist.empty()) {
9080b57cec5SDimitry Andric       const SDNode *M = Worklist.pop_back_val();
9090b57cec5SDimitry Andric       int MId = M->getNodeId();
9100b57cec5SDimitry Andric       if (TopologicalPrune && M->getOpcode() != ISD::TokenFactor && (NId > 0) &&
9110b57cec5SDimitry Andric           (MId > 0) && (MId < NId)) {
9120b57cec5SDimitry Andric         DeferredNodes.push_back(M);
9130b57cec5SDimitry Andric         continue;
9140b57cec5SDimitry Andric       }
9150b57cec5SDimitry Andric       for (const SDValue &OpV : M->op_values()) {
9160b57cec5SDimitry Andric         SDNode *Op = OpV.getNode();
9170b57cec5SDimitry Andric         if (Visited.insert(Op).second)
9180b57cec5SDimitry Andric           Worklist.push_back(Op);
9190b57cec5SDimitry Andric         if (Op == N)
9200b57cec5SDimitry Andric           Found = true;
9210b57cec5SDimitry Andric       }
9220b57cec5SDimitry Andric       if (Found)
9230b57cec5SDimitry Andric         break;
9240b57cec5SDimitry Andric       if (MaxSteps != 0 && Visited.size() >= MaxSteps)
9250b57cec5SDimitry Andric         break;
9260b57cec5SDimitry Andric     }
9270b57cec5SDimitry Andric     // Push deferred nodes back on worklist.
9280b57cec5SDimitry Andric     Worklist.append(DeferredNodes.begin(), DeferredNodes.end());
9290b57cec5SDimitry Andric     // If we bailed early, conservatively return found.
9300b57cec5SDimitry Andric     if (MaxSteps != 0 && Visited.size() >= MaxSteps)
9310b57cec5SDimitry Andric       return true;
9320b57cec5SDimitry Andric     return Found;
9330b57cec5SDimitry Andric   }
9340b57cec5SDimitry Andric 
9350b57cec5SDimitry Andric   /// Return true if all the users of N are contained in Nodes.
9360b57cec5SDimitry Andric   /// NOTE: Requires at least one match, but doesn't require them all.
9370b57cec5SDimitry Andric   static bool areOnlyUsersOf(ArrayRef<const SDNode *> Nodes, const SDNode *N);
9380b57cec5SDimitry Andric 
9390b57cec5SDimitry Andric   /// Return the number of values used by this operation.
9400b57cec5SDimitry Andric   unsigned getNumOperands() const { return NumOperands; }
9410b57cec5SDimitry Andric 
9420b57cec5SDimitry Andric   /// Return the maximum number of operands that a SDNode can hold.
9430b57cec5SDimitry Andric   static constexpr size_t getMaxNumOperands() {
9440b57cec5SDimitry Andric     return std::numeric_limits<decltype(SDNode::NumOperands)>::max();
9450b57cec5SDimitry Andric   }
9460b57cec5SDimitry Andric 
9470b57cec5SDimitry Andric   /// Helper method returns the integer value of a ConstantSDNode operand.
9480b57cec5SDimitry Andric   inline uint64_t getConstantOperandVal(unsigned Num) const;
9490b57cec5SDimitry Andric 
9501db9f3b2SDimitry Andric   /// Helper method returns the zero-extended integer value of a ConstantSDNode.
9511db9f3b2SDimitry Andric   inline uint64_t getAsZExtVal() const;
9521db9f3b2SDimitry Andric 
9530b57cec5SDimitry Andric   /// Helper method returns the APInt of a ConstantSDNode operand.
9540b57cec5SDimitry Andric   inline const APInt &getConstantOperandAPInt(unsigned Num) const;
9550b57cec5SDimitry Andric 
956297eecfbSDimitry Andric   /// Helper method returns the APInt value of a ConstantSDNode.
957297eecfbSDimitry Andric   inline const APInt &getAsAPIntVal() const;
958297eecfbSDimitry Andric 
9590b57cec5SDimitry Andric   const SDValue &getOperand(unsigned Num) const {
9600b57cec5SDimitry Andric     assert(Num < NumOperands && "Invalid child # of SDNode!");
9610b57cec5SDimitry Andric     return OperandList[Num];
9620b57cec5SDimitry Andric   }
9630b57cec5SDimitry Andric 
9640b57cec5SDimitry Andric   using op_iterator = SDUse *;
9650b57cec5SDimitry Andric 
9660b57cec5SDimitry Andric   op_iterator op_begin() const { return OperandList; }
9670b57cec5SDimitry Andric   op_iterator op_end() const { return OperandList+NumOperands; }
968bdd1243dSDimitry Andric   ArrayRef<SDUse> ops() const { return ArrayRef(op_begin(), op_end()); }
9690b57cec5SDimitry Andric 
9700b57cec5SDimitry Andric   /// Iterator for directly iterating over the operand SDValue's.
9710b57cec5SDimitry Andric   struct value_op_iterator
9720b57cec5SDimitry Andric       : iterator_adaptor_base<value_op_iterator, op_iterator,
9730b57cec5SDimitry Andric                               std::random_access_iterator_tag, SDValue,
9740b57cec5SDimitry Andric                               ptrdiff_t, value_op_iterator *,
9750b57cec5SDimitry Andric                               value_op_iterator *> {
9760b57cec5SDimitry Andric     explicit value_op_iterator(SDUse *U = nullptr)
9770b57cec5SDimitry Andric       : iterator_adaptor_base(U) {}
9780b57cec5SDimitry Andric 
9790b57cec5SDimitry Andric     const SDValue &operator*() const { return I->get(); }
9800b57cec5SDimitry Andric   };
9810b57cec5SDimitry Andric 
9820b57cec5SDimitry Andric   iterator_range<value_op_iterator> op_values() const {
9830b57cec5SDimitry Andric     return make_range(value_op_iterator(op_begin()),
9840b57cec5SDimitry Andric                       value_op_iterator(op_end()));
9850b57cec5SDimitry Andric   }
9860b57cec5SDimitry Andric 
9870b57cec5SDimitry Andric   SDVTList getVTList() const {
9880b57cec5SDimitry Andric     SDVTList X = { ValueList, NumValues };
9890b57cec5SDimitry Andric     return X;
9900b57cec5SDimitry Andric   }
9910b57cec5SDimitry Andric 
9920b57cec5SDimitry Andric   /// If this node has a glue operand, return the node
9930b57cec5SDimitry Andric   /// to which the glue operand points. Otherwise return NULL.
9940b57cec5SDimitry Andric   SDNode *getGluedNode() const {
9950b57cec5SDimitry Andric     if (getNumOperands() != 0 &&
9960b57cec5SDimitry Andric         getOperand(getNumOperands()-1).getValueType() == MVT::Glue)
9970b57cec5SDimitry Andric       return getOperand(getNumOperands()-1).getNode();
9980b57cec5SDimitry Andric     return nullptr;
9990b57cec5SDimitry Andric   }
10000b57cec5SDimitry Andric 
10010b57cec5SDimitry Andric   /// If this node has a glue value with a user, return
10020b57cec5SDimitry Andric   /// the user (there is at most one). Otherwise return NULL.
10030b57cec5SDimitry Andric   SDNode *getGluedUser() const {
10040b57cec5SDimitry Andric     for (use_iterator UI = use_begin(), UE = use_end(); UI != UE; ++UI)
10050b57cec5SDimitry Andric       if (UI.getUse().get().getValueType() == MVT::Glue)
10060b57cec5SDimitry Andric         return *UI;
10070b57cec5SDimitry Andric     return nullptr;
10080b57cec5SDimitry Andric   }
10090b57cec5SDimitry Andric 
1010fe6060f1SDimitry Andric   SDNodeFlags getFlags() const { return Flags; }
10110b57cec5SDimitry Andric   void setFlags(SDNodeFlags NewFlags) { Flags = NewFlags; }
10120b57cec5SDimitry Andric 
10130b57cec5SDimitry Andric   /// Clear any flags in this node that aren't also set in Flags.
10140b57cec5SDimitry Andric   /// If Flags is not in a defined state then this has no effect.
10150b57cec5SDimitry Andric   void intersectFlagsWith(const SDNodeFlags Flags);
10160b57cec5SDimitry Andric 
1017*0fca6ea1SDimitry Andric   bool hasPoisonGeneratingFlags() const {
1018*0fca6ea1SDimitry Andric     SDNodeFlags Flags = getFlags();
1019*0fca6ea1SDimitry Andric     return Flags.hasNoUnsignedWrap() || Flags.hasNoSignedWrap() ||
1020*0fca6ea1SDimitry Andric            Flags.hasExact() || Flags.hasDisjoint() || Flags.hasNonNeg() ||
1021*0fca6ea1SDimitry Andric            Flags.hasNoNaNs() || Flags.hasNoInfs();
1022*0fca6ea1SDimitry Andric   }
1023*0fca6ea1SDimitry Andric 
1024bdd1243dSDimitry Andric   void setCFIType(uint32_t Type) { CFIType = Type; }
1025bdd1243dSDimitry Andric   uint32_t getCFIType() const { return CFIType; }
1026bdd1243dSDimitry Andric 
10270b57cec5SDimitry Andric   /// Return the number of values defined/returned by this operator.
10280b57cec5SDimitry Andric   unsigned getNumValues() const { return NumValues; }
10290b57cec5SDimitry Andric 
10300b57cec5SDimitry Andric   /// Return the type of a specified result.
10310b57cec5SDimitry Andric   EVT getValueType(unsigned ResNo) const {
10320b57cec5SDimitry Andric     assert(ResNo < NumValues && "Illegal result number!");
10330b57cec5SDimitry Andric     return ValueList[ResNo];
10340b57cec5SDimitry Andric   }
10350b57cec5SDimitry Andric 
10360b57cec5SDimitry Andric   /// Return the type of a specified result as a simple type.
10370b57cec5SDimitry Andric   MVT getSimpleValueType(unsigned ResNo) const {
10380b57cec5SDimitry Andric     return getValueType(ResNo).getSimpleVT();
10390b57cec5SDimitry Andric   }
10400b57cec5SDimitry Andric 
10410b57cec5SDimitry Andric   /// Returns MVT::getSizeInBits(getValueType(ResNo)).
1042480093f4SDimitry Andric   ///
1043480093f4SDimitry Andric   /// If the value type is a scalable vector type, the scalable property will
1044480093f4SDimitry Andric   /// be set and the runtime size will be a positive integer multiple of the
1045480093f4SDimitry Andric   /// base size.
1046480093f4SDimitry Andric   TypeSize getValueSizeInBits(unsigned ResNo) const {
10470b57cec5SDimitry Andric     return getValueType(ResNo).getSizeInBits();
10480b57cec5SDimitry Andric   }
10490b57cec5SDimitry Andric 
10500b57cec5SDimitry Andric   using value_iterator = const EVT *;
10510b57cec5SDimitry Andric 
10520b57cec5SDimitry Andric   value_iterator value_begin() const { return ValueList; }
10530b57cec5SDimitry Andric   value_iterator value_end() const { return ValueList+NumValues; }
10545ffd83dbSDimitry Andric   iterator_range<value_iterator> values() const {
10555ffd83dbSDimitry Andric     return llvm::make_range(value_begin(), value_end());
10565ffd83dbSDimitry Andric   }
10570b57cec5SDimitry Andric 
10580b57cec5SDimitry Andric   /// Return the opcode of this operation for printing.
10590b57cec5SDimitry Andric   std::string getOperationName(const SelectionDAG *G = nullptr) const;
10600b57cec5SDimitry Andric   static const char* getIndexedModeName(ISD::MemIndexedMode AM);
10610b57cec5SDimitry Andric   void print_types(raw_ostream &OS, const SelectionDAG *G) const;
10620b57cec5SDimitry Andric   void print_details(raw_ostream &OS, const SelectionDAG *G) const;
10630b57cec5SDimitry Andric   void print(raw_ostream &OS, const SelectionDAG *G = nullptr) const;
10640b57cec5SDimitry Andric   void printr(raw_ostream &OS, const SelectionDAG *G = nullptr) const;
10650b57cec5SDimitry Andric 
10660b57cec5SDimitry Andric   /// Print a SelectionDAG node and all children down to
10670b57cec5SDimitry Andric   /// the leaves.  The given SelectionDAG allows target-specific nodes
10680b57cec5SDimitry Andric   /// to be printed in human-readable form.  Unlike printr, this will
10690b57cec5SDimitry Andric   /// print the whole DAG, including children that appear multiple
10700b57cec5SDimitry Andric   /// times.
10710b57cec5SDimitry Andric   ///
10720b57cec5SDimitry Andric   void printrFull(raw_ostream &O, const SelectionDAG *G = nullptr) const;
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric   /// Print a SelectionDAG node and children up to
10750b57cec5SDimitry Andric   /// depth "depth."  The given SelectionDAG allows target-specific
10760b57cec5SDimitry Andric   /// nodes to be printed in human-readable form.  Unlike printr, this
10770b57cec5SDimitry Andric   /// will print children that appear multiple times wherever they are
10780b57cec5SDimitry Andric   /// used.
10790b57cec5SDimitry Andric   ///
10800b57cec5SDimitry Andric   void printrWithDepth(raw_ostream &O, const SelectionDAG *G = nullptr,
10810b57cec5SDimitry Andric                        unsigned depth = 100) const;
10820b57cec5SDimitry Andric 
10830b57cec5SDimitry Andric   /// Dump this node, for debugging.
10840b57cec5SDimitry Andric   void dump() const;
10850b57cec5SDimitry Andric 
10860b57cec5SDimitry Andric   /// Dump (recursively) this node and its use-def subgraph.
10870b57cec5SDimitry Andric   void dumpr() const;
10880b57cec5SDimitry Andric 
10890b57cec5SDimitry Andric   /// Dump this node, for debugging.
10900b57cec5SDimitry Andric   /// The given SelectionDAG allows target-specific nodes to be printed
10910b57cec5SDimitry Andric   /// in human-readable form.
10920b57cec5SDimitry Andric   void dump(const SelectionDAG *G) const;
10930b57cec5SDimitry Andric 
10940b57cec5SDimitry Andric   /// Dump (recursively) this node and its use-def subgraph.
10950b57cec5SDimitry Andric   /// The given SelectionDAG allows target-specific nodes to be printed
10960b57cec5SDimitry Andric   /// in human-readable form.
10970b57cec5SDimitry Andric   void dumpr(const SelectionDAG *G) const;
10980b57cec5SDimitry Andric 
10990b57cec5SDimitry Andric   /// printrFull to dbgs().  The given SelectionDAG allows
11000b57cec5SDimitry Andric   /// target-specific nodes to be printed in human-readable form.
11010b57cec5SDimitry Andric   /// Unlike dumpr, this will print the whole DAG, including children
11020b57cec5SDimitry Andric   /// that appear multiple times.
11030b57cec5SDimitry Andric   void dumprFull(const SelectionDAG *G = nullptr) const;
11040b57cec5SDimitry Andric 
11050b57cec5SDimitry Andric   /// printrWithDepth to dbgs().  The given
11060b57cec5SDimitry Andric   /// SelectionDAG allows target-specific nodes to be printed in
11070b57cec5SDimitry Andric   /// human-readable form.  Unlike dumpr, this will print children
11080b57cec5SDimitry Andric   /// that appear multiple times wherever they are used.
11090b57cec5SDimitry Andric   ///
11100b57cec5SDimitry Andric   void dumprWithDepth(const SelectionDAG *G = nullptr,
11110b57cec5SDimitry Andric                       unsigned depth = 100) const;
11120b57cec5SDimitry Andric 
11130b57cec5SDimitry Andric   /// Gather unique data for the node.
11140b57cec5SDimitry Andric   void Profile(FoldingSetNodeID &ID) const;
11150b57cec5SDimitry Andric 
11160b57cec5SDimitry Andric   /// This method should only be used by the SDUse class.
11170b57cec5SDimitry Andric   void addUse(SDUse &U) { U.addToList(&UseList); }
11180b57cec5SDimitry Andric 
11190b57cec5SDimitry Andric protected:
11200b57cec5SDimitry Andric   static SDVTList getSDVTList(EVT VT) {
11210b57cec5SDimitry Andric     SDVTList Ret = { getValueTypeList(VT), 1 };
11220b57cec5SDimitry Andric     return Ret;
11230b57cec5SDimitry Andric   }
11240b57cec5SDimitry Andric 
11250b57cec5SDimitry Andric   /// Create an SDNode.
11260b57cec5SDimitry Andric   ///
11270b57cec5SDimitry Andric   /// SDNodes are created without any operands, and never own the operand
11280b57cec5SDimitry Andric   /// storage. To add operands, see SelectionDAG::createOperands.
11290b57cec5SDimitry Andric   SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs)
11300b57cec5SDimitry Andric       : NodeType(Opc), ValueList(VTs.VTs), NumValues(VTs.NumVTs),
11310b57cec5SDimitry Andric         IROrder(Order), debugLoc(std::move(dl)) {
11320b57cec5SDimitry Andric     memset(&RawSDNodeBits, 0, sizeof(RawSDNodeBits));
11330b57cec5SDimitry Andric     assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
11340b57cec5SDimitry Andric     assert(NumValues == VTs.NumVTs &&
11350b57cec5SDimitry Andric            "NumValues wasn't wide enough for its operands!");
11360b57cec5SDimitry Andric   }
11370b57cec5SDimitry Andric 
11380b57cec5SDimitry Andric   /// Release the operands and set this node to have zero operands.
11390b57cec5SDimitry Andric   void DropOperands();
11400b57cec5SDimitry Andric };
11410b57cec5SDimitry Andric 
11420b57cec5SDimitry Andric /// Wrapper class for IR location info (IR ordering and DebugLoc) to be passed
11430b57cec5SDimitry Andric /// into SDNode creation functions.
11440b57cec5SDimitry Andric /// When an SDNode is created from the DAGBuilder, the DebugLoc is extracted
11450b57cec5SDimitry Andric /// from the original Instruction, and IROrder is the ordinal position of
11460b57cec5SDimitry Andric /// the instruction.
11470b57cec5SDimitry Andric /// When an SDNode is created after the DAG is being built, both DebugLoc and
11480b57cec5SDimitry Andric /// the IROrder are propagated from the original SDNode.
11490b57cec5SDimitry Andric /// So SDLoc class provides two constructors besides the default one, one to
11500b57cec5SDimitry Andric /// be used by the DAGBuilder, the other to be used by others.
11510b57cec5SDimitry Andric class SDLoc {
11520b57cec5SDimitry Andric private:
11530b57cec5SDimitry Andric   DebugLoc DL;
11540b57cec5SDimitry Andric   int IROrder = 0;
11550b57cec5SDimitry Andric 
11560b57cec5SDimitry Andric public:
11570b57cec5SDimitry Andric   SDLoc() = default;
11580b57cec5SDimitry Andric   SDLoc(const SDNode *N) : DL(N->getDebugLoc()), IROrder(N->getIROrder()) {}
11590b57cec5SDimitry Andric   SDLoc(const SDValue V) : SDLoc(V.getNode()) {}
11600b57cec5SDimitry Andric   SDLoc(const Instruction *I, int Order) : IROrder(Order) {
11610b57cec5SDimitry Andric     assert(Order >= 0 && "bad IROrder");
11620b57cec5SDimitry Andric     if (I)
11630b57cec5SDimitry Andric       DL = I->getDebugLoc();
11640b57cec5SDimitry Andric   }
11650b57cec5SDimitry Andric 
11660b57cec5SDimitry Andric   unsigned getIROrder() const { return IROrder; }
11670b57cec5SDimitry Andric   const DebugLoc &getDebugLoc() const { return DL; }
11680b57cec5SDimitry Andric };
11690b57cec5SDimitry Andric 
11700b57cec5SDimitry Andric // Define inline functions from the SDValue class.
11710b57cec5SDimitry Andric 
11720b57cec5SDimitry Andric inline SDValue::SDValue(SDNode *node, unsigned resno)
11730b57cec5SDimitry Andric     : Node(node), ResNo(resno) {
11740b57cec5SDimitry Andric   // Explicitly check for !ResNo to avoid use-after-free, because there are
11750b57cec5SDimitry Andric   // callers that use SDValue(N, 0) with a deleted N to indicate successful
11760b57cec5SDimitry Andric   // combines.
11770b57cec5SDimitry Andric   assert((!Node || !ResNo || ResNo < Node->getNumValues()) &&
11780b57cec5SDimitry Andric          "Invalid result number for the given node!");
11790b57cec5SDimitry Andric   assert(ResNo < -2U && "Cannot use result numbers reserved for DenseMaps.");
11800b57cec5SDimitry Andric }
11810b57cec5SDimitry Andric 
11820b57cec5SDimitry Andric inline unsigned SDValue::getOpcode() const {
11830b57cec5SDimitry Andric   return Node->getOpcode();
11840b57cec5SDimitry Andric }
11850b57cec5SDimitry Andric 
11860b57cec5SDimitry Andric inline EVT SDValue::getValueType() const {
11870b57cec5SDimitry Andric   return Node->getValueType(ResNo);
11880b57cec5SDimitry Andric }
11890b57cec5SDimitry Andric 
11900b57cec5SDimitry Andric inline unsigned SDValue::getNumOperands() const {
11910b57cec5SDimitry Andric   return Node->getNumOperands();
11920b57cec5SDimitry Andric }
11930b57cec5SDimitry Andric 
11940b57cec5SDimitry Andric inline const SDValue &SDValue::getOperand(unsigned i) const {
11950b57cec5SDimitry Andric   return Node->getOperand(i);
11960b57cec5SDimitry Andric }
11970b57cec5SDimitry Andric 
11980b57cec5SDimitry Andric inline uint64_t SDValue::getConstantOperandVal(unsigned i) const {
11990b57cec5SDimitry Andric   return Node->getConstantOperandVal(i);
12000b57cec5SDimitry Andric }
12010b57cec5SDimitry Andric 
12020b57cec5SDimitry Andric inline const APInt &SDValue::getConstantOperandAPInt(unsigned i) const {
12030b57cec5SDimitry Andric   return Node->getConstantOperandAPInt(i);
12040b57cec5SDimitry Andric }
12050b57cec5SDimitry Andric 
12060b57cec5SDimitry Andric inline bool SDValue::isTargetOpcode() const {
12070b57cec5SDimitry Andric   return Node->isTargetOpcode();
12080b57cec5SDimitry Andric }
12090b57cec5SDimitry Andric 
12100b57cec5SDimitry Andric inline bool SDValue::isTargetMemoryOpcode() const {
12110b57cec5SDimitry Andric   return Node->isTargetMemoryOpcode();
12120b57cec5SDimitry Andric }
12130b57cec5SDimitry Andric 
12140b57cec5SDimitry Andric inline bool SDValue::isMachineOpcode() const {
12150b57cec5SDimitry Andric   return Node->isMachineOpcode();
12160b57cec5SDimitry Andric }
12170b57cec5SDimitry Andric 
12180b57cec5SDimitry Andric inline unsigned SDValue::getMachineOpcode() const {
12190b57cec5SDimitry Andric   return Node->getMachineOpcode();
12200b57cec5SDimitry Andric }
12210b57cec5SDimitry Andric 
12220b57cec5SDimitry Andric inline bool SDValue::isUndef() const {
12230b57cec5SDimitry Andric   return Node->isUndef();
12240b57cec5SDimitry Andric }
12250b57cec5SDimitry Andric 
12260b57cec5SDimitry Andric inline bool SDValue::use_empty() const {
12270b57cec5SDimitry Andric   return !Node->hasAnyUseOfValue(ResNo);
12280b57cec5SDimitry Andric }
12290b57cec5SDimitry Andric 
12300b57cec5SDimitry Andric inline bool SDValue::hasOneUse() const {
12310b57cec5SDimitry Andric   return Node->hasNUsesOfValue(1, ResNo);
12320b57cec5SDimitry Andric }
12330b57cec5SDimitry Andric 
12340b57cec5SDimitry Andric inline const DebugLoc &SDValue::getDebugLoc() const {
12350b57cec5SDimitry Andric   return Node->getDebugLoc();
12360b57cec5SDimitry Andric }
12370b57cec5SDimitry Andric 
12380b57cec5SDimitry Andric inline void SDValue::dump() const {
12390b57cec5SDimitry Andric   return Node->dump();
12400b57cec5SDimitry Andric }
12410b57cec5SDimitry Andric 
12420b57cec5SDimitry Andric inline void SDValue::dump(const SelectionDAG *G) const {
12430b57cec5SDimitry Andric   return Node->dump(G);
12440b57cec5SDimitry Andric }
12450b57cec5SDimitry Andric 
12460b57cec5SDimitry Andric inline void SDValue::dumpr() const {
12470b57cec5SDimitry Andric   return Node->dumpr();
12480b57cec5SDimitry Andric }
12490b57cec5SDimitry Andric 
12500b57cec5SDimitry Andric inline void SDValue::dumpr(const SelectionDAG *G) const {
12510b57cec5SDimitry Andric   return Node->dumpr(G);
12520b57cec5SDimitry Andric }
12530b57cec5SDimitry Andric 
12540b57cec5SDimitry Andric // Define inline functions from the SDUse class.
12550b57cec5SDimitry Andric 
12560b57cec5SDimitry Andric inline void SDUse::set(const SDValue &V) {
12570b57cec5SDimitry Andric   if (Val.getNode()) removeFromList();
12580b57cec5SDimitry Andric   Val = V;
125981ad6265SDimitry Andric   if (V.getNode())
126081ad6265SDimitry Andric     V->addUse(*this);
12610b57cec5SDimitry Andric }
12620b57cec5SDimitry Andric 
12630b57cec5SDimitry Andric inline void SDUse::setInitial(const SDValue &V) {
12640b57cec5SDimitry Andric   Val = V;
126581ad6265SDimitry Andric   V->addUse(*this);
12660b57cec5SDimitry Andric }
12670b57cec5SDimitry Andric 
12680b57cec5SDimitry Andric inline void SDUse::setNode(SDNode *N) {
12690b57cec5SDimitry Andric   if (Val.getNode()) removeFromList();
12700b57cec5SDimitry Andric   Val.setNode(N);
12710b57cec5SDimitry Andric   if (N) N->addUse(*this);
12720b57cec5SDimitry Andric }
12730b57cec5SDimitry Andric 
12740b57cec5SDimitry Andric /// This class is used to form a handle around another node that
12750b57cec5SDimitry Andric /// is persistent and is updated across invocations of replaceAllUsesWith on its
12760b57cec5SDimitry Andric /// operand.  This node should be directly created by end-users and not added to
12770b57cec5SDimitry Andric /// the AllNodes list.
12780b57cec5SDimitry Andric class HandleSDNode : public SDNode {
12790b57cec5SDimitry Andric   SDUse Op;
12800b57cec5SDimitry Andric 
12810b57cec5SDimitry Andric public:
12820b57cec5SDimitry Andric   explicit HandleSDNode(SDValue X)
12830b57cec5SDimitry Andric     : SDNode(ISD::HANDLENODE, 0, DebugLoc(), getSDVTList(MVT::Other)) {
12840b57cec5SDimitry Andric     // HandleSDNodes are never inserted into the DAG, so they won't be
12850b57cec5SDimitry Andric     // auto-numbered. Use ID 65535 as a sentinel.
12860b57cec5SDimitry Andric     PersistentId = 0xffff;
12870b57cec5SDimitry Andric 
12880b57cec5SDimitry Andric     // Manually set up the operand list. This node type is special in that it's
12890b57cec5SDimitry Andric     // always stack allocated and SelectionDAG does not manage its operands.
12900b57cec5SDimitry Andric     // TODO: This should either (a) not be in the SDNode hierarchy, or (b) not
12910b57cec5SDimitry Andric     // be so special.
12920b57cec5SDimitry Andric     Op.setUser(this);
12930b57cec5SDimitry Andric     Op.setInitial(X);
12940b57cec5SDimitry Andric     NumOperands = 1;
12950b57cec5SDimitry Andric     OperandList = &Op;
12960b57cec5SDimitry Andric   }
12970b57cec5SDimitry Andric   ~HandleSDNode();
12980b57cec5SDimitry Andric 
12990b57cec5SDimitry Andric   const SDValue &getValue() const { return Op; }
13000b57cec5SDimitry Andric };
13010b57cec5SDimitry Andric 
13020b57cec5SDimitry Andric class AddrSpaceCastSDNode : public SDNode {
13030b57cec5SDimitry Andric private:
13040b57cec5SDimitry Andric   unsigned SrcAddrSpace;
13050b57cec5SDimitry Andric   unsigned DestAddrSpace;
13060b57cec5SDimitry Andric 
13070b57cec5SDimitry Andric public:
1308*0fca6ea1SDimitry Andric   AddrSpaceCastSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
1309*0fca6ea1SDimitry Andric                       unsigned SrcAS, unsigned DestAS)
1310*0fca6ea1SDimitry Andric       : SDNode(ISD::ADDRSPACECAST, Order, dl, VTs), SrcAddrSpace(SrcAS),
1311*0fca6ea1SDimitry Andric         DestAddrSpace(DestAS) {}
13120b57cec5SDimitry Andric 
13130b57cec5SDimitry Andric   unsigned getSrcAddressSpace() const { return SrcAddrSpace; }
13140b57cec5SDimitry Andric   unsigned getDestAddressSpace() const { return DestAddrSpace; }
13150b57cec5SDimitry Andric 
13160b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
13170b57cec5SDimitry Andric     return N->getOpcode() == ISD::ADDRSPACECAST;
13180b57cec5SDimitry Andric   }
13190b57cec5SDimitry Andric };
13200b57cec5SDimitry Andric 
13210b57cec5SDimitry Andric /// This is an abstract virtual class for memory operations.
13220b57cec5SDimitry Andric class MemSDNode : public SDNode {
13230b57cec5SDimitry Andric private:
13240b57cec5SDimitry Andric   // VT of in-memory value.
13250b57cec5SDimitry Andric   EVT MemoryVT;
13260b57cec5SDimitry Andric 
13270b57cec5SDimitry Andric protected:
13280b57cec5SDimitry Andric   /// Memory reference information.
13290b57cec5SDimitry Andric   MachineMemOperand *MMO;
13300b57cec5SDimitry Andric 
13310b57cec5SDimitry Andric public:
13320b57cec5SDimitry Andric   MemSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, SDVTList VTs,
13330b57cec5SDimitry Andric             EVT memvt, MachineMemOperand *MMO);
13340b57cec5SDimitry Andric 
13350b57cec5SDimitry Andric   bool readMem() const { return MMO->isLoad(); }
13360b57cec5SDimitry Andric   bool writeMem() const { return MMO->isStore(); }
13370b57cec5SDimitry Andric 
13380b57cec5SDimitry Andric   /// Returns alignment and volatility of the memory access
13395ffd83dbSDimitry Andric   Align getOriginalAlign() const { return MMO->getBaseAlign(); }
13405ffd83dbSDimitry Andric   Align getAlign() const { return MMO->getAlign(); }
13410b57cec5SDimitry Andric 
13420b57cec5SDimitry Andric   /// Return the SubclassData value, without HasDebugValue. This contains an
13430b57cec5SDimitry Andric   /// encoding of the volatile flag, as well as bits used by subclasses. This
13440b57cec5SDimitry Andric   /// function should only be used to compute a FoldingSetNodeID value.
13450b57cec5SDimitry Andric   /// The HasDebugValue bit is masked out because CSE map needs to match
13460b57cec5SDimitry Andric   /// nodes with debug info with nodes without debug info. Same is about
13470b57cec5SDimitry Andric   /// isDivergent bit.
13480b57cec5SDimitry Andric   unsigned getRawSubclassData() const {
13490b57cec5SDimitry Andric     uint16_t Data;
13500b57cec5SDimitry Andric     union {
13510b57cec5SDimitry Andric       char RawSDNodeBits[sizeof(uint16_t)];
13520b57cec5SDimitry Andric       SDNodeBitfields SDNodeBits;
13530b57cec5SDimitry Andric     };
13540b57cec5SDimitry Andric     memcpy(&RawSDNodeBits, &this->RawSDNodeBits, sizeof(this->RawSDNodeBits));
13550b57cec5SDimitry Andric     SDNodeBits.HasDebugValue = 0;
13560b57cec5SDimitry Andric     SDNodeBits.IsDivergent = false;
13570b57cec5SDimitry Andric     memcpy(&Data, &RawSDNodeBits, sizeof(RawSDNodeBits));
13580b57cec5SDimitry Andric     return Data;
13590b57cec5SDimitry Andric   }
13600b57cec5SDimitry Andric 
13610b57cec5SDimitry Andric   bool isVolatile() const { return MemSDNodeBits.IsVolatile; }
13620b57cec5SDimitry Andric   bool isNonTemporal() const { return MemSDNodeBits.IsNonTemporal; }
13630b57cec5SDimitry Andric   bool isDereferenceable() const { return MemSDNodeBits.IsDereferenceable; }
13640b57cec5SDimitry Andric   bool isInvariant() const { return MemSDNodeBits.IsInvariant; }
13650b57cec5SDimitry Andric 
13660b57cec5SDimitry Andric   // Returns the offset from the location of the access.
13670b57cec5SDimitry Andric   int64_t getSrcValueOffset() const { return MMO->getOffset(); }
13680b57cec5SDimitry Andric 
13690b57cec5SDimitry Andric   /// Returns the AA info that describes the dereference.
13700b57cec5SDimitry Andric   AAMDNodes getAAInfo() const { return MMO->getAAInfo(); }
13710b57cec5SDimitry Andric 
13720b57cec5SDimitry Andric   /// Returns the Ranges that describes the dereference.
13730b57cec5SDimitry Andric   const MDNode *getRanges() const { return MMO->getRanges(); }
13740b57cec5SDimitry Andric 
13750b57cec5SDimitry Andric   /// Returns the synchronization scope ID for this memory operation.
13760b57cec5SDimitry Andric   SyncScope::ID getSyncScopeID() const { return MMO->getSyncScopeID(); }
13770b57cec5SDimitry Andric 
13780b57cec5SDimitry Andric   /// Return the atomic ordering requirements for this memory operation. For
13790b57cec5SDimitry Andric   /// cmpxchg atomic operations, return the atomic ordering requirements when
13800b57cec5SDimitry Andric   /// store occurs.
1381fe6060f1SDimitry Andric   AtomicOrdering getSuccessOrdering() const {
1382fe6060f1SDimitry Andric     return MMO->getSuccessOrdering();
1383fe6060f1SDimitry Andric   }
1384fe6060f1SDimitry Andric 
1385fe6060f1SDimitry Andric   /// Return a single atomic ordering that is at least as strong as both the
1386fe6060f1SDimitry Andric   /// success and failure orderings for an atomic operation.  (For operations
1387fe6060f1SDimitry Andric   /// other than cmpxchg, this is equivalent to getSuccessOrdering().)
1388fe6060f1SDimitry Andric   AtomicOrdering getMergedOrdering() const { return MMO->getMergedOrdering(); }
13890b57cec5SDimitry Andric 
13908bcb0991SDimitry Andric   /// Return true if the memory operation ordering is Unordered or higher.
13918bcb0991SDimitry Andric   bool isAtomic() const { return MMO->isAtomic(); }
13928bcb0991SDimitry Andric 
13938bcb0991SDimitry Andric   /// Returns true if the memory operation doesn't imply any ordering
13948bcb0991SDimitry Andric   /// constraints on surrounding memory operations beyond the normal memory
13958bcb0991SDimitry Andric   /// aliasing rules.
13968bcb0991SDimitry Andric   bool isUnordered() const { return MMO->isUnordered(); }
13978bcb0991SDimitry Andric 
13988bcb0991SDimitry Andric   /// Returns true if the memory operation is neither atomic or volatile.
13998bcb0991SDimitry Andric   bool isSimple() const { return !isAtomic() && !isVolatile(); }
14008bcb0991SDimitry Andric 
14010b57cec5SDimitry Andric   /// Return the type of the in-memory value.
14020b57cec5SDimitry Andric   EVT getMemoryVT() const { return MemoryVT; }
14030b57cec5SDimitry Andric 
14040b57cec5SDimitry Andric   /// Return a MachineMemOperand object describing the memory
14050b57cec5SDimitry Andric   /// reference performed by operation.
14060b57cec5SDimitry Andric   MachineMemOperand *getMemOperand() const { return MMO; }
14070b57cec5SDimitry Andric 
14080b57cec5SDimitry Andric   const MachinePointerInfo &getPointerInfo() const {
14090b57cec5SDimitry Andric     return MMO->getPointerInfo();
14100b57cec5SDimitry Andric   }
14110b57cec5SDimitry Andric 
14120b57cec5SDimitry Andric   /// Return the address space for the associated pointer
14130b57cec5SDimitry Andric   unsigned getAddressSpace() const {
14140b57cec5SDimitry Andric     return getPointerInfo().getAddrSpace();
14150b57cec5SDimitry Andric   }
14160b57cec5SDimitry Andric 
14170b57cec5SDimitry Andric   /// Update this MemSDNode's MachineMemOperand information
14180b57cec5SDimitry Andric   /// to reflect the alignment of NewMMO, if it has a greater alignment.
14190b57cec5SDimitry Andric   /// This must only be used when the new alignment applies to all users of
14200b57cec5SDimitry Andric   /// this MachineMemOperand.
14210b57cec5SDimitry Andric   void refineAlignment(const MachineMemOperand *NewMMO) {
14220b57cec5SDimitry Andric     MMO->refineAlignment(NewMMO);
14230b57cec5SDimitry Andric   }
14240b57cec5SDimitry Andric 
14250b57cec5SDimitry Andric   const SDValue &getChain() const { return getOperand(0); }
1426e8d8bef9SDimitry Andric 
14270b57cec5SDimitry Andric   const SDValue &getBasePtr() const {
1428e8d8bef9SDimitry Andric     switch (getOpcode()) {
1429e8d8bef9SDimitry Andric     case ISD::STORE:
14305f757f3fSDimitry Andric     case ISD::ATOMIC_STORE:
1431349cc55cSDimitry Andric     case ISD::VP_STORE:
1432e8d8bef9SDimitry Andric     case ISD::MSTORE:
1433349cc55cSDimitry Andric     case ISD::VP_SCATTER:
143481ad6265SDimitry Andric     case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
1435e8d8bef9SDimitry Andric       return getOperand(2);
1436e8d8bef9SDimitry Andric     case ISD::MGATHER:
1437e8d8bef9SDimitry Andric     case ISD::MSCATTER:
1438*0fca6ea1SDimitry Andric     case ISD::EXPERIMENTAL_VECTOR_HISTOGRAM:
1439e8d8bef9SDimitry Andric       return getOperand(3);
1440e8d8bef9SDimitry Andric     default:
1441e8d8bef9SDimitry Andric       return getOperand(1);
1442e8d8bef9SDimitry Andric     }
14430b57cec5SDimitry Andric   }
14440b57cec5SDimitry Andric 
14450b57cec5SDimitry Andric   // Methods to support isa and dyn_cast
14460b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
14470b57cec5SDimitry Andric     // For some targets, we lower some target intrinsics to a MemIntrinsicNode
14480b57cec5SDimitry Andric     // with either an intrinsic or a target opcode.
1449fe6060f1SDimitry Andric     switch (N->getOpcode()) {
1450fe6060f1SDimitry Andric     case ISD::LOAD:
1451fe6060f1SDimitry Andric     case ISD::STORE:
1452fe6060f1SDimitry Andric     case ISD::PREFETCH:
1453fe6060f1SDimitry Andric     case ISD::ATOMIC_CMP_SWAP:
1454fe6060f1SDimitry Andric     case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS:
1455fe6060f1SDimitry Andric     case ISD::ATOMIC_SWAP:
1456fe6060f1SDimitry Andric     case ISD::ATOMIC_LOAD_ADD:
1457fe6060f1SDimitry Andric     case ISD::ATOMIC_LOAD_SUB:
1458fe6060f1SDimitry Andric     case ISD::ATOMIC_LOAD_AND:
1459fe6060f1SDimitry Andric     case ISD::ATOMIC_LOAD_CLR:
1460fe6060f1SDimitry Andric     case ISD::ATOMIC_LOAD_OR:
1461fe6060f1SDimitry Andric     case ISD::ATOMIC_LOAD_XOR:
1462fe6060f1SDimitry Andric     case ISD::ATOMIC_LOAD_NAND:
1463fe6060f1SDimitry Andric     case ISD::ATOMIC_LOAD_MIN:
1464fe6060f1SDimitry Andric     case ISD::ATOMIC_LOAD_MAX:
1465fe6060f1SDimitry Andric     case ISD::ATOMIC_LOAD_UMIN:
1466fe6060f1SDimitry Andric     case ISD::ATOMIC_LOAD_UMAX:
1467fe6060f1SDimitry Andric     case ISD::ATOMIC_LOAD_FADD:
1468fe6060f1SDimitry Andric     case ISD::ATOMIC_LOAD_FSUB:
1469753f127fSDimitry Andric     case ISD::ATOMIC_LOAD_FMAX:
1470753f127fSDimitry Andric     case ISD::ATOMIC_LOAD_FMIN:
1471bdd1243dSDimitry Andric     case ISD::ATOMIC_LOAD_UINC_WRAP:
1472bdd1243dSDimitry Andric     case ISD::ATOMIC_LOAD_UDEC_WRAP:
1473fe6060f1SDimitry Andric     case ISD::ATOMIC_LOAD:
1474fe6060f1SDimitry Andric     case ISD::ATOMIC_STORE:
1475fe6060f1SDimitry Andric     case ISD::MLOAD:
1476fe6060f1SDimitry Andric     case ISD::MSTORE:
1477fe6060f1SDimitry Andric     case ISD::MGATHER:
1478fe6060f1SDimitry Andric     case ISD::MSCATTER:
1479349cc55cSDimitry Andric     case ISD::VP_LOAD:
1480349cc55cSDimitry Andric     case ISD::VP_STORE:
1481349cc55cSDimitry Andric     case ISD::VP_GATHER:
1482349cc55cSDimitry Andric     case ISD::VP_SCATTER:
148381ad6265SDimitry Andric     case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
148481ad6265SDimitry Andric     case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
148506c3fb27SDimitry Andric     case ISD::GET_FPENV_MEM:
148606c3fb27SDimitry Andric     case ISD::SET_FPENV_MEM:
1487*0fca6ea1SDimitry Andric     case ISD::EXPERIMENTAL_VECTOR_HISTOGRAM:
1488fe6060f1SDimitry Andric       return true;
1489fe6060f1SDimitry Andric     default:
1490fe6060f1SDimitry Andric       return N->isMemIntrinsic() || N->isTargetMemoryOpcode();
1491fe6060f1SDimitry Andric     }
14920b57cec5SDimitry Andric   }
14930b57cec5SDimitry Andric };
14940b57cec5SDimitry Andric 
14950b57cec5SDimitry Andric /// This is an SDNode representing atomic operations.
14960b57cec5SDimitry Andric class AtomicSDNode : public MemSDNode {
14970b57cec5SDimitry Andric public:
14980b57cec5SDimitry Andric   AtomicSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, SDVTList VTL,
14990b57cec5SDimitry Andric                EVT MemVT, MachineMemOperand *MMO)
15000b57cec5SDimitry Andric     : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
15010b57cec5SDimitry Andric     assert(((Opc != ISD::ATOMIC_LOAD && Opc != ISD::ATOMIC_STORE) ||
15020b57cec5SDimitry Andric             MMO->isAtomic()) && "then why are we using an AtomicSDNode?");
15030b57cec5SDimitry Andric   }
15040b57cec5SDimitry Andric 
1505*0fca6ea1SDimitry Andric   void setExtensionType(ISD::LoadExtType ETy) {
1506*0fca6ea1SDimitry Andric     assert(getOpcode() == ISD::ATOMIC_LOAD && "Only used for atomic loads.");
1507*0fca6ea1SDimitry Andric     LoadSDNodeBits.ExtTy = ETy;
1508*0fca6ea1SDimitry Andric   }
1509*0fca6ea1SDimitry Andric 
1510*0fca6ea1SDimitry Andric   ISD::LoadExtType getExtensionType() const {
1511*0fca6ea1SDimitry Andric     assert(getOpcode() == ISD::ATOMIC_LOAD && "Only used for atomic loads.");
1512*0fca6ea1SDimitry Andric     return static_cast<ISD::LoadExtType>(LoadSDNodeBits.ExtTy);
1513*0fca6ea1SDimitry Andric   }
1514*0fca6ea1SDimitry Andric 
15155f757f3fSDimitry Andric   const SDValue &getBasePtr() const {
15165f757f3fSDimitry Andric     return getOpcode() == ISD::ATOMIC_STORE ? getOperand(2) : getOperand(1);
15175f757f3fSDimitry Andric   }
15185f757f3fSDimitry Andric   const SDValue &getVal() const {
15195f757f3fSDimitry Andric     return getOpcode() == ISD::ATOMIC_STORE ? getOperand(1) : getOperand(2);
15205f757f3fSDimitry Andric   }
15210b57cec5SDimitry Andric 
15220b57cec5SDimitry Andric   /// Returns true if this SDNode represents cmpxchg atomic operation, false
15230b57cec5SDimitry Andric   /// otherwise.
15240b57cec5SDimitry Andric   bool isCompareAndSwap() const {
15250b57cec5SDimitry Andric     unsigned Op = getOpcode();
15260b57cec5SDimitry Andric     return Op == ISD::ATOMIC_CMP_SWAP ||
15270b57cec5SDimitry Andric            Op == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS;
15280b57cec5SDimitry Andric   }
15290b57cec5SDimitry Andric 
15300b57cec5SDimitry Andric   /// For cmpxchg atomic operations, return the atomic ordering requirements
15310b57cec5SDimitry Andric   /// when store does not occur.
15320b57cec5SDimitry Andric   AtomicOrdering getFailureOrdering() const {
15330b57cec5SDimitry Andric     assert(isCompareAndSwap() && "Must be cmpxchg operation");
15340b57cec5SDimitry Andric     return MMO->getFailureOrdering();
15350b57cec5SDimitry Andric   }
15360b57cec5SDimitry Andric 
15370b57cec5SDimitry Andric   // Methods to support isa and dyn_cast
15380b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
15390b57cec5SDimitry Andric     return N->getOpcode() == ISD::ATOMIC_CMP_SWAP     ||
15400b57cec5SDimitry Andric            N->getOpcode() == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS ||
15410b57cec5SDimitry Andric            N->getOpcode() == ISD::ATOMIC_SWAP         ||
15420b57cec5SDimitry Andric            N->getOpcode() == ISD::ATOMIC_LOAD_ADD     ||
15430b57cec5SDimitry Andric            N->getOpcode() == ISD::ATOMIC_LOAD_SUB     ||
15440b57cec5SDimitry Andric            N->getOpcode() == ISD::ATOMIC_LOAD_AND     ||
15450b57cec5SDimitry Andric            N->getOpcode() == ISD::ATOMIC_LOAD_CLR     ||
15460b57cec5SDimitry Andric            N->getOpcode() == ISD::ATOMIC_LOAD_OR      ||
15470b57cec5SDimitry Andric            N->getOpcode() == ISD::ATOMIC_LOAD_XOR     ||
15480b57cec5SDimitry Andric            N->getOpcode() == ISD::ATOMIC_LOAD_NAND    ||
15490b57cec5SDimitry Andric            N->getOpcode() == ISD::ATOMIC_LOAD_MIN     ||
15500b57cec5SDimitry Andric            N->getOpcode() == ISD::ATOMIC_LOAD_MAX     ||
15510b57cec5SDimitry Andric            N->getOpcode() == ISD::ATOMIC_LOAD_UMIN    ||
15520b57cec5SDimitry Andric            N->getOpcode() == ISD::ATOMIC_LOAD_UMAX    ||
15530b57cec5SDimitry Andric            N->getOpcode() == ISD::ATOMIC_LOAD_FADD    ||
15540b57cec5SDimitry Andric            N->getOpcode() == ISD::ATOMIC_LOAD_FSUB    ||
1555753f127fSDimitry Andric            N->getOpcode() == ISD::ATOMIC_LOAD_FMAX    ||
1556753f127fSDimitry Andric            N->getOpcode() == ISD::ATOMIC_LOAD_FMIN    ||
1557bdd1243dSDimitry Andric            N->getOpcode() == ISD::ATOMIC_LOAD_UINC_WRAP ||
1558bdd1243dSDimitry Andric            N->getOpcode() == ISD::ATOMIC_LOAD_UDEC_WRAP ||
15590b57cec5SDimitry Andric            N->getOpcode() == ISD::ATOMIC_LOAD         ||
15600b57cec5SDimitry Andric            N->getOpcode() == ISD::ATOMIC_STORE;
15610b57cec5SDimitry Andric   }
15620b57cec5SDimitry Andric };
15630b57cec5SDimitry Andric 
15640b57cec5SDimitry Andric /// This SDNode is used for target intrinsics that touch
15650b57cec5SDimitry Andric /// memory and need an associated MachineMemOperand. Its opcode may be
15660b57cec5SDimitry Andric /// INTRINSIC_VOID, INTRINSIC_W_CHAIN, PREFETCH, or a target-specific opcode
15670b57cec5SDimitry Andric /// with a value not less than FIRST_TARGET_MEMORY_OPCODE.
15680b57cec5SDimitry Andric class MemIntrinsicSDNode : public MemSDNode {
15690b57cec5SDimitry Andric public:
15700b57cec5SDimitry Andric   MemIntrinsicSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl,
15710b57cec5SDimitry Andric                      SDVTList VTs, EVT MemoryVT, MachineMemOperand *MMO)
15720b57cec5SDimitry Andric       : MemSDNode(Opc, Order, dl, VTs, MemoryVT, MMO) {
15730b57cec5SDimitry Andric     SDNodeBits.IsMemIntrinsic = true;
15740b57cec5SDimitry Andric   }
15750b57cec5SDimitry Andric 
15760b57cec5SDimitry Andric   // Methods to support isa and dyn_cast
15770b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
15780b57cec5SDimitry Andric     // We lower some target intrinsics to their target opcode
15790b57cec5SDimitry Andric     // early a node with a target opcode can be of this class
15800b57cec5SDimitry Andric     return N->isMemIntrinsic()             ||
15810b57cec5SDimitry Andric            N->getOpcode() == ISD::PREFETCH ||
15820b57cec5SDimitry Andric            N->isTargetMemoryOpcode();
15830b57cec5SDimitry Andric   }
15840b57cec5SDimitry Andric };
15850b57cec5SDimitry Andric 
15860b57cec5SDimitry Andric /// This SDNode is used to implement the code generator
15870b57cec5SDimitry Andric /// support for the llvm IR shufflevector instruction.  It combines elements
15880b57cec5SDimitry Andric /// from two input vectors into a new input vector, with the selection and
15890b57cec5SDimitry Andric /// ordering of elements determined by an array of integers, referred to as
15900b57cec5SDimitry Andric /// the shuffle mask.  For input vectors of width N, mask indices of 0..N-1
15910b57cec5SDimitry Andric /// refer to elements from the LHS input, and indices from N to 2N-1 the RHS.
15920b57cec5SDimitry Andric /// An index of -1 is treated as undef, such that the code generator may put
15930b57cec5SDimitry Andric /// any value in the corresponding element of the result.
15940b57cec5SDimitry Andric class ShuffleVectorSDNode : public SDNode {
15950b57cec5SDimitry Andric   // The memory for Mask is owned by the SelectionDAG's OperandAllocator, and
15960b57cec5SDimitry Andric   // is freed when the SelectionDAG object is destroyed.
15970b57cec5SDimitry Andric   const int *Mask;
15980b57cec5SDimitry Andric 
15990b57cec5SDimitry Andric protected:
16000b57cec5SDimitry Andric   friend class SelectionDAG;
16010b57cec5SDimitry Andric 
1602*0fca6ea1SDimitry Andric   ShuffleVectorSDNode(SDVTList VTs, unsigned Order, const DebugLoc &dl,
1603*0fca6ea1SDimitry Andric                       const int *M)
1604*0fca6ea1SDimitry Andric       : SDNode(ISD::VECTOR_SHUFFLE, Order, dl, VTs), Mask(M) {}
16050b57cec5SDimitry Andric 
16060b57cec5SDimitry Andric public:
16070b57cec5SDimitry Andric   ArrayRef<int> getMask() const {
16080b57cec5SDimitry Andric     EVT VT = getValueType(0);
1609bdd1243dSDimitry Andric     return ArrayRef(Mask, VT.getVectorNumElements());
16100b57cec5SDimitry Andric   }
16110b57cec5SDimitry Andric 
16120b57cec5SDimitry Andric   int getMaskElt(unsigned Idx) const {
16130b57cec5SDimitry Andric     assert(Idx < getValueType(0).getVectorNumElements() && "Idx out of range!");
16140b57cec5SDimitry Andric     return Mask[Idx];
16150b57cec5SDimitry Andric   }
16160b57cec5SDimitry Andric 
16170b57cec5SDimitry Andric   bool isSplat() const { return isSplatMask(Mask, getValueType(0)); }
16180b57cec5SDimitry Andric 
16190b57cec5SDimitry Andric   int getSplatIndex() const {
16200b57cec5SDimitry Andric     assert(isSplat() && "Cannot get splat index for non-splat!");
16210b57cec5SDimitry Andric     EVT VT = getValueType(0);
16220b57cec5SDimitry Andric     for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i)
16230b57cec5SDimitry Andric       if (Mask[i] >= 0)
16240b57cec5SDimitry Andric         return Mask[i];
16250b57cec5SDimitry Andric 
16260b57cec5SDimitry Andric     // We can choose any index value here and be correct because all elements
16270b57cec5SDimitry Andric     // are undefined. Return 0 for better potential for callers to simplify.
16280b57cec5SDimitry Andric     return 0;
16290b57cec5SDimitry Andric   }
16300b57cec5SDimitry Andric 
16310b57cec5SDimitry Andric   static bool isSplatMask(const int *Mask, EVT VT);
16320b57cec5SDimitry Andric 
16330b57cec5SDimitry Andric   /// Change values in a shuffle permute mask assuming
16340b57cec5SDimitry Andric   /// the two vector operands have swapped position.
16350b57cec5SDimitry Andric   static void commuteMask(MutableArrayRef<int> Mask) {
16360b57cec5SDimitry Andric     unsigned NumElems = Mask.size();
16370b57cec5SDimitry Andric     for (unsigned i = 0; i != NumElems; ++i) {
16380b57cec5SDimitry Andric       int idx = Mask[i];
16390b57cec5SDimitry Andric       if (idx < 0)
16400b57cec5SDimitry Andric         continue;
16410b57cec5SDimitry Andric       else if (idx < (int)NumElems)
16420b57cec5SDimitry Andric         Mask[i] = idx + NumElems;
16430b57cec5SDimitry Andric       else
16440b57cec5SDimitry Andric         Mask[i] = idx - NumElems;
16450b57cec5SDimitry Andric     }
16460b57cec5SDimitry Andric   }
16470b57cec5SDimitry Andric 
16480b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
16490b57cec5SDimitry Andric     return N->getOpcode() == ISD::VECTOR_SHUFFLE;
16500b57cec5SDimitry Andric   }
16510b57cec5SDimitry Andric };
16520b57cec5SDimitry Andric 
16530b57cec5SDimitry Andric class ConstantSDNode : public SDNode {
16540b57cec5SDimitry Andric   friend class SelectionDAG;
16550b57cec5SDimitry Andric 
16560b57cec5SDimitry Andric   const ConstantInt *Value;
16570b57cec5SDimitry Andric 
1658*0fca6ea1SDimitry Andric   ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val,
1659*0fca6ea1SDimitry Andric                  SDVTList VTs)
16600b57cec5SDimitry Andric       : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, 0, DebugLoc(),
1661*0fca6ea1SDimitry Andric                VTs),
16620b57cec5SDimitry Andric         Value(val) {
16630b57cec5SDimitry Andric     ConstantSDNodeBits.IsOpaque = isOpaque;
16640b57cec5SDimitry Andric   }
16650b57cec5SDimitry Andric 
16660b57cec5SDimitry Andric public:
16670b57cec5SDimitry Andric   const ConstantInt *getConstantIntValue() const { return Value; }
16680b57cec5SDimitry Andric   const APInt &getAPIntValue() const { return Value->getValue(); }
16690b57cec5SDimitry Andric   uint64_t getZExtValue() const { return Value->getZExtValue(); }
16700b57cec5SDimitry Andric   int64_t getSExtValue() const { return Value->getSExtValue(); }
16710b57cec5SDimitry Andric   uint64_t getLimitedValue(uint64_t Limit = UINT64_MAX) {
16720b57cec5SDimitry Andric     return Value->getLimitedValue(Limit);
16730b57cec5SDimitry Andric   }
16745ffd83dbSDimitry Andric   MaybeAlign getMaybeAlignValue() const { return Value->getMaybeAlignValue(); }
16755ffd83dbSDimitry Andric   Align getAlignValue() const { return Value->getAlignValue(); }
16760b57cec5SDimitry Andric 
16770b57cec5SDimitry Andric   bool isOne() const { return Value->isOne(); }
1678349cc55cSDimitry Andric   bool isZero() const { return Value->isZero(); }
1679349cc55cSDimitry Andric   bool isAllOnes() const { return Value->isMinusOne(); }
1680fe6060f1SDimitry Andric   bool isMaxSignedValue() const { return Value->isMaxValue(true); }
1681fe6060f1SDimitry Andric   bool isMinSignedValue() const { return Value->isMinValue(true); }
16820b57cec5SDimitry Andric 
16830b57cec5SDimitry Andric   bool isOpaque() const { return ConstantSDNodeBits.IsOpaque; }
16840b57cec5SDimitry Andric 
16850b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
16860b57cec5SDimitry Andric     return N->getOpcode() == ISD::Constant ||
16870b57cec5SDimitry Andric            N->getOpcode() == ISD::TargetConstant;
16880b57cec5SDimitry Andric   }
16890b57cec5SDimitry Andric };
16900b57cec5SDimitry Andric 
16910b57cec5SDimitry Andric uint64_t SDNode::getConstantOperandVal(unsigned Num) const {
16920b57cec5SDimitry Andric   return cast<ConstantSDNode>(getOperand(Num))->getZExtValue();
16930b57cec5SDimitry Andric }
16940b57cec5SDimitry Andric 
16951db9f3b2SDimitry Andric uint64_t SDNode::getAsZExtVal() const {
16961db9f3b2SDimitry Andric   return cast<ConstantSDNode>(this)->getZExtValue();
16971db9f3b2SDimitry Andric }
16981db9f3b2SDimitry Andric 
16990b57cec5SDimitry Andric const APInt &SDNode::getConstantOperandAPInt(unsigned Num) const {
17000b57cec5SDimitry Andric   return cast<ConstantSDNode>(getOperand(Num))->getAPIntValue();
17010b57cec5SDimitry Andric }
17020b57cec5SDimitry Andric 
1703297eecfbSDimitry Andric const APInt &SDNode::getAsAPIntVal() const {
1704297eecfbSDimitry Andric   return cast<ConstantSDNode>(this)->getAPIntValue();
1705297eecfbSDimitry Andric }
1706297eecfbSDimitry Andric 
17070b57cec5SDimitry Andric class ConstantFPSDNode : public SDNode {
17080b57cec5SDimitry Andric   friend class SelectionDAG;
17090b57cec5SDimitry Andric 
17100b57cec5SDimitry Andric   const ConstantFP *Value;
17110b57cec5SDimitry Andric 
1712*0fca6ea1SDimitry Andric   ConstantFPSDNode(bool isTarget, const ConstantFP *val, SDVTList VTs)
17130b57cec5SDimitry Andric       : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, 0,
1714*0fca6ea1SDimitry Andric                DebugLoc(), VTs),
17150b57cec5SDimitry Andric         Value(val) {}
17160b57cec5SDimitry Andric 
17170b57cec5SDimitry Andric public:
17180b57cec5SDimitry Andric   const APFloat& getValueAPF() const { return Value->getValueAPF(); }
17190b57cec5SDimitry Andric   const ConstantFP *getConstantFPValue() const { return Value; }
17200b57cec5SDimitry Andric 
17210b57cec5SDimitry Andric   /// Return true if the value is positive or negative zero.
17220b57cec5SDimitry Andric   bool isZero() const { return Value->isZero(); }
17230b57cec5SDimitry Andric 
17240b57cec5SDimitry Andric   /// Return true if the value is a NaN.
17250b57cec5SDimitry Andric   bool isNaN() const { return Value->isNaN(); }
17260b57cec5SDimitry Andric 
17270b57cec5SDimitry Andric   /// Return true if the value is an infinity
17280b57cec5SDimitry Andric   bool isInfinity() const { return Value->isInfinity(); }
17290b57cec5SDimitry Andric 
17300b57cec5SDimitry Andric   /// Return true if the value is negative.
17310b57cec5SDimitry Andric   bool isNegative() const { return Value->isNegative(); }
17320b57cec5SDimitry Andric 
17330b57cec5SDimitry Andric   /// We don't rely on operator== working on double values, as
17340b57cec5SDimitry Andric   /// it returns true for things that are clearly not equal, like -0.0 and 0.0.
17350b57cec5SDimitry Andric   /// As such, this method can be used to do an exact bit-for-bit comparison of
17360b57cec5SDimitry Andric   /// two floating point values.
17370b57cec5SDimitry Andric 
17380b57cec5SDimitry Andric   /// We leave the version with the double argument here because it's just so
17390b57cec5SDimitry Andric   /// convenient to write "2.0" and the like.  Without this function we'd
17400b57cec5SDimitry Andric   /// have to duplicate its logic everywhere it's called.
17410b57cec5SDimitry Andric   bool isExactlyValue(double V) const {
17420b57cec5SDimitry Andric     return Value->getValueAPF().isExactlyValue(V);
17430b57cec5SDimitry Andric   }
17440b57cec5SDimitry Andric   bool isExactlyValue(const APFloat& V) const;
17450b57cec5SDimitry Andric 
17460b57cec5SDimitry Andric   static bool isValueValidForType(EVT VT, const APFloat& Val);
17470b57cec5SDimitry Andric 
17480b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
17490b57cec5SDimitry Andric     return N->getOpcode() == ISD::ConstantFP ||
17500b57cec5SDimitry Andric            N->getOpcode() == ISD::TargetConstantFP;
17510b57cec5SDimitry Andric   }
17520b57cec5SDimitry Andric };
17530b57cec5SDimitry Andric 
17540b57cec5SDimitry Andric /// Returns true if \p V is a constant integer zero.
17550b57cec5SDimitry Andric bool isNullConstant(SDValue V);
17560b57cec5SDimitry Andric 
1757*0fca6ea1SDimitry Andric /// Returns true if \p V is a constant integer zero or an UNDEF node.
1758*0fca6ea1SDimitry Andric bool isNullConstantOrUndef(SDValue V);
1759*0fca6ea1SDimitry Andric 
17600b57cec5SDimitry Andric /// Returns true if \p V is an FP constant with a value of positive zero.
17610b57cec5SDimitry Andric bool isNullFPConstant(SDValue V);
17620b57cec5SDimitry Andric 
17630b57cec5SDimitry Andric /// Returns true if \p V is an integer constant with all bits set.
17640b57cec5SDimitry Andric bool isAllOnesConstant(SDValue V);
17650b57cec5SDimitry Andric 
17660b57cec5SDimitry Andric /// Returns true if \p V is a constant integer one.
17670b57cec5SDimitry Andric bool isOneConstant(SDValue V);
17680b57cec5SDimitry Andric 
176981ad6265SDimitry Andric /// Returns true if \p V is a constant min signed integer value.
177081ad6265SDimitry Andric bool isMinSignedConstant(SDValue V);
177181ad6265SDimitry Andric 
1772bdd1243dSDimitry Andric /// Returns true if \p V is a neutral element of Opc with Flags.
1773bdd1243dSDimitry Andric /// When OperandNo is 0, it checks that V is a left identity. Otherwise, it
1774bdd1243dSDimitry Andric /// checks that V is a right identity.
1775bdd1243dSDimitry Andric bool isNeutralConstant(unsigned Opc, SDNodeFlags Flags, SDValue V,
1776bdd1243dSDimitry Andric                        unsigned OperandNo);
1777bdd1243dSDimitry Andric 
17780b57cec5SDimitry Andric /// Return the non-bitcasted source operand of \p V if it exists.
17790b57cec5SDimitry Andric /// If \p V is not a bitcasted value, it is returned as-is.
17800b57cec5SDimitry Andric SDValue peekThroughBitcasts(SDValue V);
17810b57cec5SDimitry Andric 
17820b57cec5SDimitry Andric /// Return the non-bitcasted and one-use source operand of \p V if it exists.
17830b57cec5SDimitry Andric /// If \p V is not a bitcasted one-use value, it is returned as-is.
17840b57cec5SDimitry Andric SDValue peekThroughOneUseBitcasts(SDValue V);
17850b57cec5SDimitry Andric 
17860b57cec5SDimitry Andric /// Return the non-extracted vector source operand of \p V if it exists.
17870b57cec5SDimitry Andric /// If \p V is not an extracted subvector, it is returned as-is.
17880b57cec5SDimitry Andric SDValue peekThroughExtractSubvectors(SDValue V);
17890b57cec5SDimitry Andric 
179006c3fb27SDimitry Andric /// Return the non-truncated source operand of \p V if it exists.
179106c3fb27SDimitry Andric /// If \p V is not a truncation, it is returned as-is.
179206c3fb27SDimitry Andric SDValue peekThroughTruncates(SDValue V);
179306c3fb27SDimitry Andric 
17940b57cec5SDimitry Andric /// Returns true if \p V is a bitwise not operation. Assumes that an all ones
17950b57cec5SDimitry Andric /// constant is canonicalized to be operand 1.
17960b57cec5SDimitry Andric bool isBitwiseNot(SDValue V, bool AllowUndefs = false);
17970b57cec5SDimitry Andric 
179881ad6265SDimitry Andric /// If \p V is a bitwise not, returns the inverted operand. Otherwise returns
179981ad6265SDimitry Andric /// an empty SDValue. Only bits set in \p Mask are required to be inverted,
180081ad6265SDimitry Andric /// other bits may be arbitrary.
180181ad6265SDimitry Andric SDValue getBitwiseNotOperand(SDValue V, SDValue Mask, bool AllowUndefs);
180281ad6265SDimitry Andric 
18030b57cec5SDimitry Andric /// Returns the SDNode if it is a constant splat BuildVector or constant int.
18040b57cec5SDimitry Andric ConstantSDNode *isConstOrConstSplat(SDValue N, bool AllowUndefs = false,
18050b57cec5SDimitry Andric                                     bool AllowTruncation = false);
18060b57cec5SDimitry Andric 
18070b57cec5SDimitry Andric /// Returns the SDNode if it is a demanded constant splat BuildVector or
18080b57cec5SDimitry Andric /// constant int.
18090b57cec5SDimitry Andric ConstantSDNode *isConstOrConstSplat(SDValue N, const APInt &DemandedElts,
18100b57cec5SDimitry Andric                                     bool AllowUndefs = false,
18110b57cec5SDimitry Andric                                     bool AllowTruncation = false);
18120b57cec5SDimitry Andric 
18130b57cec5SDimitry Andric /// Returns the SDNode if it is a constant splat BuildVector or constant float.
18140b57cec5SDimitry Andric ConstantFPSDNode *isConstOrConstSplatFP(SDValue N, bool AllowUndefs = false);
18150b57cec5SDimitry Andric 
18160b57cec5SDimitry Andric /// Returns the SDNode if it is a demanded constant splat BuildVector or
18170b57cec5SDimitry Andric /// constant float.
18180b57cec5SDimitry Andric ConstantFPSDNode *isConstOrConstSplatFP(SDValue N, const APInt &DemandedElts,
18190b57cec5SDimitry Andric                                         bool AllowUndefs = false);
18200b57cec5SDimitry Andric 
18210b57cec5SDimitry Andric /// Return true if the value is a constant 0 integer or a splatted vector of
18220b57cec5SDimitry Andric /// a constant 0 integer (with no undefs by default).
18230b57cec5SDimitry Andric /// Build vector implicit truncation is not an issue for null values.
18240b57cec5SDimitry Andric bool isNullOrNullSplat(SDValue V, bool AllowUndefs = false);
18250b57cec5SDimitry Andric 
18260b57cec5SDimitry Andric /// Return true if the value is a constant 1 integer or a splatted vector of a
18270b57cec5SDimitry Andric /// constant 1 integer (with no undefs).
1828bdd1243dSDimitry Andric /// Build vector implicit truncation is allowed, but the truncated bits need to
1829bdd1243dSDimitry Andric /// be zero.
1830fe6060f1SDimitry Andric bool isOneOrOneSplat(SDValue V, bool AllowUndefs = false);
18310b57cec5SDimitry Andric 
18320b57cec5SDimitry Andric /// Return true if the value is a constant -1 integer or a splatted vector of a
18330b57cec5SDimitry Andric /// constant -1 integer (with no undefs).
18340b57cec5SDimitry Andric /// Does not permit build vector implicit truncation.
1835fe6060f1SDimitry Andric bool isAllOnesOrAllOnesSplat(SDValue V, bool AllowUndefs = false);
1836fe6060f1SDimitry Andric 
1837fe6060f1SDimitry Andric /// Return true if \p V is either a integer or FP constant.
1838fe6060f1SDimitry Andric inline bool isIntOrFPConstant(SDValue V) {
1839fe6060f1SDimitry Andric   return isa<ConstantSDNode>(V) || isa<ConstantFPSDNode>(V);
1840fe6060f1SDimitry Andric }
18410b57cec5SDimitry Andric 
18420b57cec5SDimitry Andric class GlobalAddressSDNode : public SDNode {
18430b57cec5SDimitry Andric   friend class SelectionDAG;
18440b57cec5SDimitry Andric 
18450b57cec5SDimitry Andric   const GlobalValue *TheGlobal;
18460b57cec5SDimitry Andric   int64_t Offset;
18478bcb0991SDimitry Andric   unsigned TargetFlags;
18480b57cec5SDimitry Andric 
18490b57cec5SDimitry Andric   GlobalAddressSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL,
1850*0fca6ea1SDimitry Andric                       const GlobalValue *GA, SDVTList VTs, int64_t o,
1851*0fca6ea1SDimitry Andric                       unsigned TF)
1852*0fca6ea1SDimitry Andric       : SDNode(Opc, Order, DL, VTs), TheGlobal(GA), Offset(o), TargetFlags(TF) {
1853*0fca6ea1SDimitry Andric   }
18540b57cec5SDimitry Andric 
18550b57cec5SDimitry Andric public:
18560b57cec5SDimitry Andric   const GlobalValue *getGlobal() const { return TheGlobal; }
18570b57cec5SDimitry Andric   int64_t getOffset() const { return Offset; }
18588bcb0991SDimitry Andric   unsigned getTargetFlags() const { return TargetFlags; }
18590b57cec5SDimitry Andric   // Return the address space this GlobalAddress belongs to.
18600b57cec5SDimitry Andric   unsigned getAddressSpace() const;
18610b57cec5SDimitry Andric 
18620b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
18630b57cec5SDimitry Andric     return N->getOpcode() == ISD::GlobalAddress ||
18640b57cec5SDimitry Andric            N->getOpcode() == ISD::TargetGlobalAddress ||
18650b57cec5SDimitry Andric            N->getOpcode() == ISD::GlobalTLSAddress ||
18660b57cec5SDimitry Andric            N->getOpcode() == ISD::TargetGlobalTLSAddress;
18670b57cec5SDimitry Andric   }
18680b57cec5SDimitry Andric };
18690b57cec5SDimitry Andric 
18700b57cec5SDimitry Andric class FrameIndexSDNode : public SDNode {
18710b57cec5SDimitry Andric   friend class SelectionDAG;
18720b57cec5SDimitry Andric 
18730b57cec5SDimitry Andric   int FI;
18740b57cec5SDimitry Andric 
1875*0fca6ea1SDimitry Andric   FrameIndexSDNode(int fi, SDVTList VTs, bool isTarg)
1876*0fca6ea1SDimitry Andric       : SDNode(isTarg ? ISD::TargetFrameIndex : ISD::FrameIndex, 0, DebugLoc(),
1877*0fca6ea1SDimitry Andric                VTs),
1878*0fca6ea1SDimitry Andric         FI(fi) {}
18790b57cec5SDimitry Andric 
18800b57cec5SDimitry Andric public:
18810b57cec5SDimitry Andric   int getIndex() const { return FI; }
18820b57cec5SDimitry Andric 
18830b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
18840b57cec5SDimitry Andric     return N->getOpcode() == ISD::FrameIndex ||
18850b57cec5SDimitry Andric            N->getOpcode() == ISD::TargetFrameIndex;
18860b57cec5SDimitry Andric   }
18870b57cec5SDimitry Andric };
18880b57cec5SDimitry Andric 
18890b57cec5SDimitry Andric /// This SDNode is used for LIFETIME_START/LIFETIME_END values, which indicate
18900b57cec5SDimitry Andric /// the offet and size that are started/ended in the underlying FrameIndex.
18910b57cec5SDimitry Andric class LifetimeSDNode : public SDNode {
18920b57cec5SDimitry Andric   friend class SelectionDAG;
18930b57cec5SDimitry Andric   int64_t Size;
18940b57cec5SDimitry Andric   int64_t Offset; // -1 if offset is unknown.
18950b57cec5SDimitry Andric 
18960b57cec5SDimitry Andric   LifetimeSDNode(unsigned Opcode, unsigned Order, const DebugLoc &dl,
18970b57cec5SDimitry Andric                  SDVTList VTs, int64_t Size, int64_t Offset)
18980b57cec5SDimitry Andric       : SDNode(Opcode, Order, dl, VTs), Size(Size), Offset(Offset) {}
18990b57cec5SDimitry Andric public:
19000b57cec5SDimitry Andric   int64_t getFrameIndex() const {
19010b57cec5SDimitry Andric     return cast<FrameIndexSDNode>(getOperand(1))->getIndex();
19020b57cec5SDimitry Andric   }
19030b57cec5SDimitry Andric 
19040b57cec5SDimitry Andric   bool hasOffset() const { return Offset >= 0; }
19050b57cec5SDimitry Andric   int64_t getOffset() const {
19060b57cec5SDimitry Andric     assert(hasOffset() && "offset is unknown");
19070b57cec5SDimitry Andric     return Offset;
19080b57cec5SDimitry Andric   }
19090b57cec5SDimitry Andric   int64_t getSize() const {
19100b57cec5SDimitry Andric     assert(hasOffset() && "offset is unknown");
19110b57cec5SDimitry Andric     return Size;
19120b57cec5SDimitry Andric   }
19130b57cec5SDimitry Andric 
19140b57cec5SDimitry Andric   // Methods to support isa and dyn_cast
19150b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
19160b57cec5SDimitry Andric     return N->getOpcode() == ISD::LIFETIME_START ||
19170b57cec5SDimitry Andric            N->getOpcode() == ISD::LIFETIME_END;
19180b57cec5SDimitry Andric   }
19190b57cec5SDimitry Andric };
19200b57cec5SDimitry Andric 
1921e8d8bef9SDimitry Andric /// This SDNode is used for PSEUDO_PROBE values, which are the function guid and
1922e8d8bef9SDimitry Andric /// the index of the basic block being probed. A pseudo probe serves as a place
1923e8d8bef9SDimitry Andric /// holder and will be removed at the end of compilation. It does not have any
1924e8d8bef9SDimitry Andric /// operand because we do not want the instruction selection to deal with any.
1925e8d8bef9SDimitry Andric class PseudoProbeSDNode : public SDNode {
1926e8d8bef9SDimitry Andric   friend class SelectionDAG;
1927e8d8bef9SDimitry Andric   uint64_t Guid;
1928e8d8bef9SDimitry Andric   uint64_t Index;
1929e8d8bef9SDimitry Andric   uint32_t Attributes;
1930e8d8bef9SDimitry Andric 
1931e8d8bef9SDimitry Andric   PseudoProbeSDNode(unsigned Opcode, unsigned Order, const DebugLoc &Dl,
1932e8d8bef9SDimitry Andric                     SDVTList VTs, uint64_t Guid, uint64_t Index, uint32_t Attr)
1933e8d8bef9SDimitry Andric       : SDNode(Opcode, Order, Dl, VTs), Guid(Guid), Index(Index),
1934e8d8bef9SDimitry Andric         Attributes(Attr) {}
1935e8d8bef9SDimitry Andric 
1936e8d8bef9SDimitry Andric public:
1937e8d8bef9SDimitry Andric   uint64_t getGuid() const { return Guid; }
1938e8d8bef9SDimitry Andric   uint64_t getIndex() const { return Index; }
1939e8d8bef9SDimitry Andric   uint32_t getAttributes() const { return Attributes; }
1940e8d8bef9SDimitry Andric 
1941e8d8bef9SDimitry Andric   // Methods to support isa and dyn_cast
1942e8d8bef9SDimitry Andric   static bool classof(const SDNode *N) {
1943e8d8bef9SDimitry Andric     return N->getOpcode() == ISD::PSEUDO_PROBE;
1944e8d8bef9SDimitry Andric   }
1945e8d8bef9SDimitry Andric };
1946e8d8bef9SDimitry Andric 
19470b57cec5SDimitry Andric class JumpTableSDNode : public SDNode {
19480b57cec5SDimitry Andric   friend class SelectionDAG;
19490b57cec5SDimitry Andric 
19500b57cec5SDimitry Andric   int JTI;
19518bcb0991SDimitry Andric   unsigned TargetFlags;
19520b57cec5SDimitry Andric 
1953*0fca6ea1SDimitry Andric   JumpTableSDNode(int jti, SDVTList VTs, bool isTarg, unsigned TF)
1954*0fca6ea1SDimitry Andric       : SDNode(isTarg ? ISD::TargetJumpTable : ISD::JumpTable, 0, DebugLoc(),
1955*0fca6ea1SDimitry Andric                VTs),
1956*0fca6ea1SDimitry Andric         JTI(jti), TargetFlags(TF) {}
19570b57cec5SDimitry Andric 
19580b57cec5SDimitry Andric public:
19590b57cec5SDimitry Andric   int getIndex() const { return JTI; }
19608bcb0991SDimitry Andric   unsigned getTargetFlags() const { return TargetFlags; }
19610b57cec5SDimitry Andric 
19620b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
19630b57cec5SDimitry Andric     return N->getOpcode() == ISD::JumpTable ||
19640b57cec5SDimitry Andric            N->getOpcode() == ISD::TargetJumpTable;
19650b57cec5SDimitry Andric   }
19660b57cec5SDimitry Andric };
19670b57cec5SDimitry Andric 
19680b57cec5SDimitry Andric class ConstantPoolSDNode : public SDNode {
19690b57cec5SDimitry Andric   friend class SelectionDAG;
19700b57cec5SDimitry Andric 
19710b57cec5SDimitry Andric   union {
19720b57cec5SDimitry Andric     const Constant *ConstVal;
19730b57cec5SDimitry Andric     MachineConstantPoolValue *MachineCPVal;
19740b57cec5SDimitry Andric   } Val;
19750b57cec5SDimitry Andric   int Offset;  // It's a MachineConstantPoolValue if top bit is set.
19765ffd83dbSDimitry Andric   Align Alignment; // Minimum alignment requirement of CP.
19778bcb0991SDimitry Andric   unsigned TargetFlags;
19780b57cec5SDimitry Andric 
1979*0fca6ea1SDimitry Andric   ConstantPoolSDNode(bool isTarget, const Constant *c, SDVTList VTs, int o,
19805ffd83dbSDimitry Andric                      Align Alignment, unsigned TF)
19810b57cec5SDimitry Andric       : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, 0,
1982*0fca6ea1SDimitry Andric                DebugLoc(), VTs),
19835ffd83dbSDimitry Andric         Offset(o), Alignment(Alignment), TargetFlags(TF) {
19840b57cec5SDimitry Andric     assert(Offset >= 0 && "Offset is too large");
19850b57cec5SDimitry Andric     Val.ConstVal = c;
19860b57cec5SDimitry Andric   }
19870b57cec5SDimitry Andric 
1988*0fca6ea1SDimitry Andric   ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v, SDVTList VTs,
1989*0fca6ea1SDimitry Andric                      int o, Align Alignment, unsigned TF)
19900b57cec5SDimitry Andric       : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, 0,
1991*0fca6ea1SDimitry Andric                DebugLoc(), VTs),
19925ffd83dbSDimitry Andric         Offset(o), Alignment(Alignment), TargetFlags(TF) {
19930b57cec5SDimitry Andric     assert(Offset >= 0 && "Offset is too large");
19940b57cec5SDimitry Andric     Val.MachineCPVal = v;
19950b57cec5SDimitry Andric     Offset |= 1 << (sizeof(unsigned)*CHAR_BIT-1);
19960b57cec5SDimitry Andric   }
19970b57cec5SDimitry Andric 
19980b57cec5SDimitry Andric public:
19990b57cec5SDimitry Andric   bool isMachineConstantPoolEntry() const {
20000b57cec5SDimitry Andric     return Offset < 0;
20010b57cec5SDimitry Andric   }
20020b57cec5SDimitry Andric 
20030b57cec5SDimitry Andric   const Constant *getConstVal() const {
20040b57cec5SDimitry Andric     assert(!isMachineConstantPoolEntry() && "Wrong constantpool type");
20050b57cec5SDimitry Andric     return Val.ConstVal;
20060b57cec5SDimitry Andric   }
20070b57cec5SDimitry Andric 
20080b57cec5SDimitry Andric   MachineConstantPoolValue *getMachineCPVal() const {
20090b57cec5SDimitry Andric     assert(isMachineConstantPoolEntry() && "Wrong constantpool type");
20100b57cec5SDimitry Andric     return Val.MachineCPVal;
20110b57cec5SDimitry Andric   }
20120b57cec5SDimitry Andric 
20130b57cec5SDimitry Andric   int getOffset() const {
20140b57cec5SDimitry Andric     return Offset & ~(1 << (sizeof(unsigned)*CHAR_BIT-1));
20150b57cec5SDimitry Andric   }
20160b57cec5SDimitry Andric 
20170b57cec5SDimitry Andric   // Return the alignment of this constant pool object, which is either 0 (for
20180b57cec5SDimitry Andric   // default alignment) or the desired value.
20195ffd83dbSDimitry Andric   Align getAlign() const { return Alignment; }
20208bcb0991SDimitry Andric   unsigned getTargetFlags() const { return TargetFlags; }
20210b57cec5SDimitry Andric 
20220b57cec5SDimitry Andric   Type *getType() const;
20230b57cec5SDimitry Andric 
20240b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
20250b57cec5SDimitry Andric     return N->getOpcode() == ISD::ConstantPool ||
20260b57cec5SDimitry Andric            N->getOpcode() == ISD::TargetConstantPool;
20270b57cec5SDimitry Andric   }
20280b57cec5SDimitry Andric };
20290b57cec5SDimitry Andric 
20300b57cec5SDimitry Andric /// Completely target-dependent object reference.
20310b57cec5SDimitry Andric class TargetIndexSDNode : public SDNode {
20320b57cec5SDimitry Andric   friend class SelectionDAG;
20330b57cec5SDimitry Andric 
20348bcb0991SDimitry Andric   unsigned TargetFlags;
20350b57cec5SDimitry Andric   int Index;
20360b57cec5SDimitry Andric   int64_t Offset;
20370b57cec5SDimitry Andric 
20380b57cec5SDimitry Andric public:
2039*0fca6ea1SDimitry Andric   TargetIndexSDNode(int Idx, SDVTList VTs, int64_t Ofs, unsigned TF)
2040*0fca6ea1SDimitry Andric       : SDNode(ISD::TargetIndex, 0, DebugLoc(), VTs), TargetFlags(TF),
2041*0fca6ea1SDimitry Andric         Index(Idx), Offset(Ofs) {}
20420b57cec5SDimitry Andric 
20438bcb0991SDimitry Andric   unsigned getTargetFlags() const { return TargetFlags; }
20440b57cec5SDimitry Andric   int getIndex() const { return Index; }
20450b57cec5SDimitry Andric   int64_t getOffset() const { return Offset; }
20460b57cec5SDimitry Andric 
20470b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
20480b57cec5SDimitry Andric     return N->getOpcode() == ISD::TargetIndex;
20490b57cec5SDimitry Andric   }
20500b57cec5SDimitry Andric };
20510b57cec5SDimitry Andric 
20520b57cec5SDimitry Andric class BasicBlockSDNode : public SDNode {
20530b57cec5SDimitry Andric   friend class SelectionDAG;
20540b57cec5SDimitry Andric 
20550b57cec5SDimitry Andric   MachineBasicBlock *MBB;
20560b57cec5SDimitry Andric 
20570b57cec5SDimitry Andric   /// Debug info is meaningful and potentially useful here, but we create
20580b57cec5SDimitry Andric   /// blocks out of order when they're jumped to, which makes it a bit
20590b57cec5SDimitry Andric   /// harder.  Let's see if we need it first.
20600b57cec5SDimitry Andric   explicit BasicBlockSDNode(MachineBasicBlock *mbb)
20610b57cec5SDimitry Andric     : SDNode(ISD::BasicBlock, 0, DebugLoc(), getSDVTList(MVT::Other)), MBB(mbb)
20620b57cec5SDimitry Andric   {}
20630b57cec5SDimitry Andric 
20640b57cec5SDimitry Andric public:
20650b57cec5SDimitry Andric   MachineBasicBlock *getBasicBlock() const { return MBB; }
20660b57cec5SDimitry Andric 
20670b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
20680b57cec5SDimitry Andric     return N->getOpcode() == ISD::BasicBlock;
20690b57cec5SDimitry Andric   }
20700b57cec5SDimitry Andric };
20710b57cec5SDimitry Andric 
20720b57cec5SDimitry Andric /// A "pseudo-class" with methods for operating on BUILD_VECTORs.
20730b57cec5SDimitry Andric class BuildVectorSDNode : public SDNode {
20740b57cec5SDimitry Andric public:
20750b57cec5SDimitry Andric   // These are constructed as SDNodes and then cast to BuildVectorSDNodes.
20760b57cec5SDimitry Andric   explicit BuildVectorSDNode() = delete;
20770b57cec5SDimitry Andric 
20780b57cec5SDimitry Andric   /// Check if this is a constant splat, and if so, find the
20790b57cec5SDimitry Andric   /// smallest element size that splats the vector.  If MinSplatBits is
20800b57cec5SDimitry Andric   /// nonzero, the element size must be at least that large.  Note that the
20810b57cec5SDimitry Andric   /// splat element may be the entire vector (i.e., a one element vector).
20820b57cec5SDimitry Andric   /// Returns the splat element value in SplatValue.  Any undefined bits in
20830b57cec5SDimitry Andric   /// that value are zero, and the corresponding bits in the SplatUndef mask
20840b57cec5SDimitry Andric   /// are set.  The SplatBitSize value is set to the splat element size in
20850b57cec5SDimitry Andric   /// bits.  HasAnyUndefs is set to true if any bits in the vector are
20860b57cec5SDimitry Andric   /// undefined.  isBigEndian describes the endianness of the target.
20870b57cec5SDimitry Andric   bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef,
20880b57cec5SDimitry Andric                        unsigned &SplatBitSize, bool &HasAnyUndefs,
20890b57cec5SDimitry Andric                        unsigned MinSplatBits = 0,
20900b57cec5SDimitry Andric                        bool isBigEndian = false) const;
20910b57cec5SDimitry Andric 
20920b57cec5SDimitry Andric   /// Returns the demanded splatted value or a null value if this is not a
20930b57cec5SDimitry Andric   /// splat.
20940b57cec5SDimitry Andric   ///
20950b57cec5SDimitry Andric   /// The DemandedElts mask indicates the elements that must be in the splat.
20960b57cec5SDimitry Andric   /// If passed a non-null UndefElements bitvector, it will resize it to match
20970b57cec5SDimitry Andric   /// the vector width and set the bits where elements are undef.
20980b57cec5SDimitry Andric   SDValue getSplatValue(const APInt &DemandedElts,
20990b57cec5SDimitry Andric                         BitVector *UndefElements = nullptr) const;
21000b57cec5SDimitry Andric 
21010b57cec5SDimitry Andric   /// Returns the splatted value or a null value if this is not a splat.
21020b57cec5SDimitry Andric   ///
21030b57cec5SDimitry Andric   /// If passed a non-null UndefElements bitvector, it will resize it to match
21040b57cec5SDimitry Andric   /// the vector width and set the bits where elements are undef.
21050b57cec5SDimitry Andric   SDValue getSplatValue(BitVector *UndefElements = nullptr) const;
21060b57cec5SDimitry Andric 
2107e8d8bef9SDimitry Andric   /// Find the shortest repeating sequence of values in the build vector.
2108e8d8bef9SDimitry Andric   ///
2109e8d8bef9SDimitry Andric   /// e.g. { u, X, u, X, u, u, X, u } -> { X }
2110e8d8bef9SDimitry Andric   ///      { X, Y, u, Y, u, u, X, u } -> { X, Y }
2111e8d8bef9SDimitry Andric   ///
2112e8d8bef9SDimitry Andric   /// Currently this must be a power-of-2 build vector.
2113e8d8bef9SDimitry Andric   /// The DemandedElts mask indicates the elements that must be present,
2114e8d8bef9SDimitry Andric   /// undemanded elements in Sequence may be null (SDValue()). If passed a
2115e8d8bef9SDimitry Andric   /// non-null UndefElements bitvector, it will resize it to match the original
2116e8d8bef9SDimitry Andric   /// vector width and set the bits where elements are undef. If result is
2117e8d8bef9SDimitry Andric   /// false, Sequence will be empty.
2118e8d8bef9SDimitry Andric   bool getRepeatedSequence(const APInt &DemandedElts,
2119e8d8bef9SDimitry Andric                            SmallVectorImpl<SDValue> &Sequence,
2120e8d8bef9SDimitry Andric                            BitVector *UndefElements = nullptr) const;
2121e8d8bef9SDimitry Andric 
2122e8d8bef9SDimitry Andric   /// Find the shortest repeating sequence of values in the build vector.
2123e8d8bef9SDimitry Andric   ///
2124e8d8bef9SDimitry Andric   /// e.g. { u, X, u, X, u, u, X, u } -> { X }
2125e8d8bef9SDimitry Andric   ///      { X, Y, u, Y, u, u, X, u } -> { X, Y }
2126e8d8bef9SDimitry Andric   ///
2127e8d8bef9SDimitry Andric   /// Currently this must be a power-of-2 build vector.
2128e8d8bef9SDimitry Andric   /// If passed a non-null UndefElements bitvector, it will resize it to match
2129e8d8bef9SDimitry Andric   /// the original vector width and set the bits where elements are undef.
2130e8d8bef9SDimitry Andric   /// If result is false, Sequence will be empty.
2131e8d8bef9SDimitry Andric   bool getRepeatedSequence(SmallVectorImpl<SDValue> &Sequence,
2132e8d8bef9SDimitry Andric                            BitVector *UndefElements = nullptr) const;
2133e8d8bef9SDimitry Andric 
21340b57cec5SDimitry Andric   /// Returns the demanded splatted constant or null if this is not a constant
21350b57cec5SDimitry Andric   /// splat.
21360b57cec5SDimitry Andric   ///
21370b57cec5SDimitry Andric   /// The DemandedElts mask indicates the elements that must be in the splat.
21380b57cec5SDimitry Andric   /// If passed a non-null UndefElements bitvector, it will resize it to match
21390b57cec5SDimitry Andric   /// the vector width and set the bits where elements are undef.
21400b57cec5SDimitry Andric   ConstantSDNode *
21410b57cec5SDimitry Andric   getConstantSplatNode(const APInt &DemandedElts,
21420b57cec5SDimitry Andric                        BitVector *UndefElements = nullptr) const;
21430b57cec5SDimitry Andric 
21440b57cec5SDimitry Andric   /// Returns the splatted constant or null if this is not a constant
21450b57cec5SDimitry Andric   /// splat.
21460b57cec5SDimitry Andric   ///
21470b57cec5SDimitry Andric   /// If passed a non-null UndefElements bitvector, it will resize it to match
21480b57cec5SDimitry Andric   /// the vector width and set the bits where elements are undef.
21490b57cec5SDimitry Andric   ConstantSDNode *
21500b57cec5SDimitry Andric   getConstantSplatNode(BitVector *UndefElements = nullptr) const;
21510b57cec5SDimitry Andric 
21520b57cec5SDimitry Andric   /// Returns the demanded splatted constant FP or null if this is not a
21530b57cec5SDimitry Andric   /// constant FP splat.
21540b57cec5SDimitry Andric   ///
21550b57cec5SDimitry Andric   /// The DemandedElts mask indicates the elements that must be in the splat.
21560b57cec5SDimitry Andric   /// If passed a non-null UndefElements bitvector, it will resize it to match
21570b57cec5SDimitry Andric   /// the vector width and set the bits where elements are undef.
21580b57cec5SDimitry Andric   ConstantFPSDNode *
21590b57cec5SDimitry Andric   getConstantFPSplatNode(const APInt &DemandedElts,
21600b57cec5SDimitry Andric                          BitVector *UndefElements = nullptr) const;
21610b57cec5SDimitry Andric 
21620b57cec5SDimitry Andric   /// Returns the splatted constant FP or null if this is not a constant
21630b57cec5SDimitry Andric   /// FP splat.
21640b57cec5SDimitry Andric   ///
21650b57cec5SDimitry Andric   /// If passed a non-null UndefElements bitvector, it will resize it to match
21660b57cec5SDimitry Andric   /// the vector width and set the bits where elements are undef.
21670b57cec5SDimitry Andric   ConstantFPSDNode *
21680b57cec5SDimitry Andric   getConstantFPSplatNode(BitVector *UndefElements = nullptr) const;
21690b57cec5SDimitry Andric 
21700b57cec5SDimitry Andric   /// If this is a constant FP splat and the splatted constant FP is an
21710b57cec5SDimitry Andric   /// exact power or 2, return the log base 2 integer value.  Otherwise,
21720b57cec5SDimitry Andric   /// return -1.
21730b57cec5SDimitry Andric   ///
21740b57cec5SDimitry Andric   /// The BitWidth specifies the necessary bit precision.
21750b57cec5SDimitry Andric   int32_t getConstantFPSplatPow2ToLog2Int(BitVector *UndefElements,
21760b57cec5SDimitry Andric                                           uint32_t BitWidth) const;
21770b57cec5SDimitry Andric 
2178349cc55cSDimitry Andric   /// Extract the raw bit data from a build vector of Undef, Constant or
2179349cc55cSDimitry Andric   /// ConstantFP node elements. Each raw bit element will be \p
2180349cc55cSDimitry Andric   /// DstEltSizeInBits wide, undef elements are treated as zero, and entirely
2181349cc55cSDimitry Andric   /// undefined elements are flagged in \p UndefElements.
2182349cc55cSDimitry Andric   bool getConstantRawBits(bool IsLittleEndian, unsigned DstEltSizeInBits,
2183349cc55cSDimitry Andric                           SmallVectorImpl<APInt> &RawBitElements,
2184349cc55cSDimitry Andric                           BitVector &UndefElements) const;
2185349cc55cSDimitry Andric 
21860b57cec5SDimitry Andric   bool isConstant() const;
21870b57cec5SDimitry Andric 
2188972a253aSDimitry Andric   /// If this BuildVector is constant and represents the numerical series
2189bdd1243dSDimitry Andric   /// "<a, a+n, a+2n, a+3n, ...>" where a is integer and n is a non-zero integer,
2190bdd1243dSDimitry Andric   /// the value "<a,n>" is returned.
2191bdd1243dSDimitry Andric   std::optional<std::pair<APInt, APInt>> isConstantSequence() const;
2192972a253aSDimitry Andric 
2193349cc55cSDimitry Andric   /// Recast bit data \p SrcBitElements to \p DstEltSizeInBits wide elements.
2194349cc55cSDimitry Andric   /// Undef elements are treated as zero, and entirely undefined elements are
2195349cc55cSDimitry Andric   /// flagged in \p DstUndefElements.
2196349cc55cSDimitry Andric   static void recastRawBits(bool IsLittleEndian, unsigned DstEltSizeInBits,
2197349cc55cSDimitry Andric                             SmallVectorImpl<APInt> &DstBitElements,
2198349cc55cSDimitry Andric                             ArrayRef<APInt> SrcBitElements,
2199349cc55cSDimitry Andric                             BitVector &DstUndefElements,
2200349cc55cSDimitry Andric                             const BitVector &SrcUndefElements);
2201349cc55cSDimitry Andric 
22020b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
22030b57cec5SDimitry Andric     return N->getOpcode() == ISD::BUILD_VECTOR;
22040b57cec5SDimitry Andric   }
22050b57cec5SDimitry Andric };
22060b57cec5SDimitry Andric 
22070b57cec5SDimitry Andric /// An SDNode that holds an arbitrary LLVM IR Value. This is
22080b57cec5SDimitry Andric /// used when the SelectionDAG needs to make a simple reference to something
22090b57cec5SDimitry Andric /// in the LLVM IR representation.
22100b57cec5SDimitry Andric ///
22110b57cec5SDimitry Andric class SrcValueSDNode : public SDNode {
22120b57cec5SDimitry Andric   friend class SelectionDAG;
22130b57cec5SDimitry Andric 
22140b57cec5SDimitry Andric   const Value *V;
22150b57cec5SDimitry Andric 
22160b57cec5SDimitry Andric   /// Create a SrcValue for a general value.
22170b57cec5SDimitry Andric   explicit SrcValueSDNode(const Value *v)
22180b57cec5SDimitry Andric     : SDNode(ISD::SRCVALUE, 0, DebugLoc(), getSDVTList(MVT::Other)), V(v) {}
22190b57cec5SDimitry Andric 
22200b57cec5SDimitry Andric public:
22210b57cec5SDimitry Andric   /// Return the contained Value.
22220b57cec5SDimitry Andric   const Value *getValue() const { return V; }
22230b57cec5SDimitry Andric 
22240b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
22250b57cec5SDimitry Andric     return N->getOpcode() == ISD::SRCVALUE;
22260b57cec5SDimitry Andric   }
22270b57cec5SDimitry Andric };
22280b57cec5SDimitry Andric 
22290b57cec5SDimitry Andric class MDNodeSDNode : public SDNode {
22300b57cec5SDimitry Andric   friend class SelectionDAG;
22310b57cec5SDimitry Andric 
22320b57cec5SDimitry Andric   const MDNode *MD;
22330b57cec5SDimitry Andric 
22340b57cec5SDimitry Andric   explicit MDNodeSDNode(const MDNode *md)
22350b57cec5SDimitry Andric   : SDNode(ISD::MDNODE_SDNODE, 0, DebugLoc(), getSDVTList(MVT::Other)), MD(md)
22360b57cec5SDimitry Andric   {}
22370b57cec5SDimitry Andric 
22380b57cec5SDimitry Andric public:
22390b57cec5SDimitry Andric   const MDNode *getMD() const { return MD; }
22400b57cec5SDimitry Andric 
22410b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
22420b57cec5SDimitry Andric     return N->getOpcode() == ISD::MDNODE_SDNODE;
22430b57cec5SDimitry Andric   }
22440b57cec5SDimitry Andric };
22450b57cec5SDimitry Andric 
22460b57cec5SDimitry Andric class RegisterSDNode : public SDNode {
22470b57cec5SDimitry Andric   friend class SelectionDAG;
22480b57cec5SDimitry Andric 
22495ffd83dbSDimitry Andric   Register Reg;
22500b57cec5SDimitry Andric 
2251*0fca6ea1SDimitry Andric   RegisterSDNode(Register reg, SDVTList VTs)
2252*0fca6ea1SDimitry Andric       : SDNode(ISD::Register, 0, DebugLoc(), VTs), Reg(reg) {}
22530b57cec5SDimitry Andric 
22540b57cec5SDimitry Andric public:
22555ffd83dbSDimitry Andric   Register getReg() const { return Reg; }
22560b57cec5SDimitry Andric 
22570b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
22580b57cec5SDimitry Andric     return N->getOpcode() == ISD::Register;
22590b57cec5SDimitry Andric   }
22600b57cec5SDimitry Andric };
22610b57cec5SDimitry Andric 
22620b57cec5SDimitry Andric class RegisterMaskSDNode : public SDNode {
22630b57cec5SDimitry Andric   friend class SelectionDAG;
22640b57cec5SDimitry Andric 
22650b57cec5SDimitry Andric   // The memory for RegMask is not owned by the node.
22660b57cec5SDimitry Andric   const uint32_t *RegMask;
22670b57cec5SDimitry Andric 
22680b57cec5SDimitry Andric   RegisterMaskSDNode(const uint32_t *mask)
22690b57cec5SDimitry Andric     : SDNode(ISD::RegisterMask, 0, DebugLoc(), getSDVTList(MVT::Untyped)),
22700b57cec5SDimitry Andric       RegMask(mask) {}
22710b57cec5SDimitry Andric 
22720b57cec5SDimitry Andric public:
22730b57cec5SDimitry Andric   const uint32_t *getRegMask() const { return RegMask; }
22740b57cec5SDimitry Andric 
22750b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
22760b57cec5SDimitry Andric     return N->getOpcode() == ISD::RegisterMask;
22770b57cec5SDimitry Andric   }
22780b57cec5SDimitry Andric };
22790b57cec5SDimitry Andric 
22800b57cec5SDimitry Andric class BlockAddressSDNode : public SDNode {
22810b57cec5SDimitry Andric   friend class SelectionDAG;
22820b57cec5SDimitry Andric 
22830b57cec5SDimitry Andric   const BlockAddress *BA;
22840b57cec5SDimitry Andric   int64_t Offset;
22858bcb0991SDimitry Andric   unsigned TargetFlags;
22860b57cec5SDimitry Andric 
2287*0fca6ea1SDimitry Andric   BlockAddressSDNode(unsigned NodeTy, SDVTList VTs, const BlockAddress *ba,
22888bcb0991SDimitry Andric                      int64_t o, unsigned Flags)
2289*0fca6ea1SDimitry Andric       : SDNode(NodeTy, 0, DebugLoc(), VTs), BA(ba), Offset(o),
2290*0fca6ea1SDimitry Andric         TargetFlags(Flags) {}
22910b57cec5SDimitry Andric 
22920b57cec5SDimitry Andric public:
22930b57cec5SDimitry Andric   const BlockAddress *getBlockAddress() const { return BA; }
22940b57cec5SDimitry Andric   int64_t getOffset() const { return Offset; }
22958bcb0991SDimitry Andric   unsigned getTargetFlags() const { return TargetFlags; }
22960b57cec5SDimitry Andric 
22970b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
22980b57cec5SDimitry Andric     return N->getOpcode() == ISD::BlockAddress ||
22990b57cec5SDimitry Andric            N->getOpcode() == ISD::TargetBlockAddress;
23000b57cec5SDimitry Andric   }
23010b57cec5SDimitry Andric };
23020b57cec5SDimitry Andric 
23030b57cec5SDimitry Andric class LabelSDNode : public SDNode {
23040b57cec5SDimitry Andric   friend class SelectionDAG;
23050b57cec5SDimitry Andric 
23060b57cec5SDimitry Andric   MCSymbol *Label;
23070b57cec5SDimitry Andric 
23080b57cec5SDimitry Andric   LabelSDNode(unsigned Opcode, unsigned Order, const DebugLoc &dl, MCSymbol *L)
23090b57cec5SDimitry Andric       : SDNode(Opcode, Order, dl, getSDVTList(MVT::Other)), Label(L) {
23100b57cec5SDimitry Andric     assert(LabelSDNode::classof(this) && "not a label opcode");
23110b57cec5SDimitry Andric   }
23120b57cec5SDimitry Andric 
23130b57cec5SDimitry Andric public:
23140b57cec5SDimitry Andric   MCSymbol *getLabel() const { return Label; }
23150b57cec5SDimitry Andric 
23160b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
23170b57cec5SDimitry Andric     return N->getOpcode() == ISD::EH_LABEL ||
23180b57cec5SDimitry Andric            N->getOpcode() == ISD::ANNOTATION_LABEL;
23190b57cec5SDimitry Andric   }
23200b57cec5SDimitry Andric };
23210b57cec5SDimitry Andric 
23220b57cec5SDimitry Andric class ExternalSymbolSDNode : public SDNode {
23230b57cec5SDimitry Andric   friend class SelectionDAG;
23240b57cec5SDimitry Andric 
23250b57cec5SDimitry Andric   const char *Symbol;
23268bcb0991SDimitry Andric   unsigned TargetFlags;
23270b57cec5SDimitry Andric 
2328*0fca6ea1SDimitry Andric   ExternalSymbolSDNode(bool isTarget, const char *Sym, unsigned TF,
2329*0fca6ea1SDimitry Andric                        SDVTList VTs)
23308bcb0991SDimitry Andric       : SDNode(isTarget ? ISD::TargetExternalSymbol : ISD::ExternalSymbol, 0,
2331*0fca6ea1SDimitry Andric                DebugLoc(), VTs),
23328bcb0991SDimitry Andric         Symbol(Sym), TargetFlags(TF) {}
23330b57cec5SDimitry Andric 
23340b57cec5SDimitry Andric public:
23350b57cec5SDimitry Andric   const char *getSymbol() const { return Symbol; }
23368bcb0991SDimitry Andric   unsigned getTargetFlags() const { return TargetFlags; }
23370b57cec5SDimitry Andric 
23380b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
23390b57cec5SDimitry Andric     return N->getOpcode() == ISD::ExternalSymbol ||
23400b57cec5SDimitry Andric            N->getOpcode() == ISD::TargetExternalSymbol;
23410b57cec5SDimitry Andric   }
23420b57cec5SDimitry Andric };
23430b57cec5SDimitry Andric 
23440b57cec5SDimitry Andric class MCSymbolSDNode : public SDNode {
23450b57cec5SDimitry Andric   friend class SelectionDAG;
23460b57cec5SDimitry Andric 
23470b57cec5SDimitry Andric   MCSymbol *Symbol;
23480b57cec5SDimitry Andric 
2349*0fca6ea1SDimitry Andric   MCSymbolSDNode(MCSymbol *Symbol, SDVTList VTs)
2350*0fca6ea1SDimitry Andric       : SDNode(ISD::MCSymbol, 0, DebugLoc(), VTs), Symbol(Symbol) {}
23510b57cec5SDimitry Andric 
23520b57cec5SDimitry Andric public:
23530b57cec5SDimitry Andric   MCSymbol *getMCSymbol() const { return Symbol; }
23540b57cec5SDimitry Andric 
23550b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
23560b57cec5SDimitry Andric     return N->getOpcode() == ISD::MCSymbol;
23570b57cec5SDimitry Andric   }
23580b57cec5SDimitry Andric };
23590b57cec5SDimitry Andric 
23600b57cec5SDimitry Andric class CondCodeSDNode : public SDNode {
23610b57cec5SDimitry Andric   friend class SelectionDAG;
23620b57cec5SDimitry Andric 
23630b57cec5SDimitry Andric   ISD::CondCode Condition;
23640b57cec5SDimitry Andric 
23650b57cec5SDimitry Andric   explicit CondCodeSDNode(ISD::CondCode Cond)
23660b57cec5SDimitry Andric     : SDNode(ISD::CONDCODE, 0, DebugLoc(), getSDVTList(MVT::Other)),
23670b57cec5SDimitry Andric       Condition(Cond) {}
23680b57cec5SDimitry Andric 
23690b57cec5SDimitry Andric public:
23700b57cec5SDimitry Andric   ISD::CondCode get() const { return Condition; }
23710b57cec5SDimitry Andric 
23720b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
23730b57cec5SDimitry Andric     return N->getOpcode() == ISD::CONDCODE;
23740b57cec5SDimitry Andric   }
23750b57cec5SDimitry Andric };
23760b57cec5SDimitry Andric 
23770b57cec5SDimitry Andric /// This class is used to represent EVT's, which are used
23780b57cec5SDimitry Andric /// to parameterize some operations.
23790b57cec5SDimitry Andric class VTSDNode : public SDNode {
23800b57cec5SDimitry Andric   friend class SelectionDAG;
23810b57cec5SDimitry Andric 
23820b57cec5SDimitry Andric   EVT ValueType;
23830b57cec5SDimitry Andric 
23840b57cec5SDimitry Andric   explicit VTSDNode(EVT VT)
23850b57cec5SDimitry Andric     : SDNode(ISD::VALUETYPE, 0, DebugLoc(), getSDVTList(MVT::Other)),
23860b57cec5SDimitry Andric       ValueType(VT) {}
23870b57cec5SDimitry Andric 
23880b57cec5SDimitry Andric public:
23890b57cec5SDimitry Andric   EVT getVT() const { return ValueType; }
23900b57cec5SDimitry Andric 
23910b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
23920b57cec5SDimitry Andric     return N->getOpcode() == ISD::VALUETYPE;
23930b57cec5SDimitry Andric   }
23940b57cec5SDimitry Andric };
23950b57cec5SDimitry Andric 
23960b57cec5SDimitry Andric /// Base class for LoadSDNode and StoreSDNode
23970b57cec5SDimitry Andric class LSBaseSDNode : public MemSDNode {
23980b57cec5SDimitry Andric public:
23990b57cec5SDimitry Andric   LSBaseSDNode(ISD::NodeType NodeTy, unsigned Order, const DebugLoc &dl,
24000b57cec5SDimitry Andric                SDVTList VTs, ISD::MemIndexedMode AM, EVT MemVT,
24010b57cec5SDimitry Andric                MachineMemOperand *MMO)
24020b57cec5SDimitry Andric       : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {
24030b57cec5SDimitry Andric     LSBaseSDNodeBits.AddressingMode = AM;
24040b57cec5SDimitry Andric     assert(getAddressingMode() == AM && "Value truncated");
24050b57cec5SDimitry Andric   }
24060b57cec5SDimitry Andric 
24070b57cec5SDimitry Andric   const SDValue &getOffset() const {
24080b57cec5SDimitry Andric     return getOperand(getOpcode() == ISD::LOAD ? 2 : 3);
24090b57cec5SDimitry Andric   }
24100b57cec5SDimitry Andric 
24110b57cec5SDimitry Andric   /// Return the addressing mode for this load or store:
24120b57cec5SDimitry Andric   /// unindexed, pre-inc, pre-dec, post-inc, or post-dec.
24130b57cec5SDimitry Andric   ISD::MemIndexedMode getAddressingMode() const {
24140b57cec5SDimitry Andric     return static_cast<ISD::MemIndexedMode>(LSBaseSDNodeBits.AddressingMode);
24150b57cec5SDimitry Andric   }
24160b57cec5SDimitry Andric 
24170b57cec5SDimitry Andric   /// Return true if this is a pre/post inc/dec load/store.
24180b57cec5SDimitry Andric   bool isIndexed() const { return getAddressingMode() != ISD::UNINDEXED; }
24190b57cec5SDimitry Andric 
24200b57cec5SDimitry Andric   /// Return true if this is NOT a pre/post inc/dec load/store.
24210b57cec5SDimitry Andric   bool isUnindexed() const { return getAddressingMode() == ISD::UNINDEXED; }
24220b57cec5SDimitry Andric 
24230b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
24240b57cec5SDimitry Andric     return N->getOpcode() == ISD::LOAD ||
24250b57cec5SDimitry Andric            N->getOpcode() == ISD::STORE;
24260b57cec5SDimitry Andric   }
24270b57cec5SDimitry Andric };
24280b57cec5SDimitry Andric 
24290b57cec5SDimitry Andric /// This class is used to represent ISD::LOAD nodes.
24300b57cec5SDimitry Andric class LoadSDNode : public LSBaseSDNode {
24310b57cec5SDimitry Andric   friend class SelectionDAG;
24320b57cec5SDimitry Andric 
24330b57cec5SDimitry Andric   LoadSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
24340b57cec5SDimitry Andric              ISD::MemIndexedMode AM, ISD::LoadExtType ETy, EVT MemVT,
24350b57cec5SDimitry Andric              MachineMemOperand *MMO)
24360b57cec5SDimitry Andric       : LSBaseSDNode(ISD::LOAD, Order, dl, VTs, AM, MemVT, MMO) {
24370b57cec5SDimitry Andric     LoadSDNodeBits.ExtTy = ETy;
24380b57cec5SDimitry Andric     assert(readMem() && "Load MachineMemOperand is not a load!");
24390b57cec5SDimitry Andric     assert(!writeMem() && "Load MachineMemOperand is a store!");
24400b57cec5SDimitry Andric   }
24410b57cec5SDimitry Andric 
24420b57cec5SDimitry Andric public:
24430b57cec5SDimitry Andric   /// Return whether this is a plain node,
24440b57cec5SDimitry Andric   /// or one of the varieties of value-extending loads.
24450b57cec5SDimitry Andric   ISD::LoadExtType getExtensionType() const {
24460b57cec5SDimitry Andric     return static_cast<ISD::LoadExtType>(LoadSDNodeBits.ExtTy);
24470b57cec5SDimitry Andric   }
24480b57cec5SDimitry Andric 
24490b57cec5SDimitry Andric   const SDValue &getBasePtr() const { return getOperand(1); }
24500b57cec5SDimitry Andric   const SDValue &getOffset() const { return getOperand(2); }
24510b57cec5SDimitry Andric 
24520b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
24530b57cec5SDimitry Andric     return N->getOpcode() == ISD::LOAD;
24540b57cec5SDimitry Andric   }
24550b57cec5SDimitry Andric };
24560b57cec5SDimitry Andric 
24570b57cec5SDimitry Andric /// This class is used to represent ISD::STORE nodes.
24580b57cec5SDimitry Andric class StoreSDNode : public LSBaseSDNode {
24590b57cec5SDimitry Andric   friend class SelectionDAG;
24600b57cec5SDimitry Andric 
24610b57cec5SDimitry Andric   StoreSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
24620b57cec5SDimitry Andric               ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT,
24630b57cec5SDimitry Andric               MachineMemOperand *MMO)
24640b57cec5SDimitry Andric       : LSBaseSDNode(ISD::STORE, Order, dl, VTs, AM, MemVT, MMO) {
24650b57cec5SDimitry Andric     StoreSDNodeBits.IsTruncating = isTrunc;
24660b57cec5SDimitry Andric     assert(!readMem() && "Store MachineMemOperand is a load!");
24670b57cec5SDimitry Andric     assert(writeMem() && "Store MachineMemOperand is not a store!");
24680b57cec5SDimitry Andric   }
24690b57cec5SDimitry Andric 
24700b57cec5SDimitry Andric public:
24710b57cec5SDimitry Andric   /// Return true if the op does a truncation before store.
24720b57cec5SDimitry Andric   /// For integers this is the same as doing a TRUNCATE and storing the result.
24730b57cec5SDimitry Andric   /// For floats, it is the same as doing an FP_ROUND and storing the result.
24740b57cec5SDimitry Andric   bool isTruncatingStore() const { return StoreSDNodeBits.IsTruncating; }
24750b57cec5SDimitry Andric   void setTruncatingStore(bool Truncating) {
24760b57cec5SDimitry Andric     StoreSDNodeBits.IsTruncating = Truncating;
24770b57cec5SDimitry Andric   }
24780b57cec5SDimitry Andric 
24790b57cec5SDimitry Andric   const SDValue &getValue() const { return getOperand(1); }
24800b57cec5SDimitry Andric   const SDValue &getBasePtr() const { return getOperand(2); }
24810b57cec5SDimitry Andric   const SDValue &getOffset() const { return getOperand(3); }
24820b57cec5SDimitry Andric 
24830b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
24840b57cec5SDimitry Andric     return N->getOpcode() == ISD::STORE;
24850b57cec5SDimitry Andric   }
24860b57cec5SDimitry Andric };
24870b57cec5SDimitry Andric 
248881ad6265SDimitry Andric /// This base class is used to represent VP_LOAD, VP_STORE,
248981ad6265SDimitry Andric /// EXPERIMENTAL_VP_STRIDED_LOAD and EXPERIMENTAL_VP_STRIDED_STORE nodes
249081ad6265SDimitry Andric class VPBaseLoadStoreSDNode : public MemSDNode {
2491349cc55cSDimitry Andric public:
2492349cc55cSDimitry Andric   friend class SelectionDAG;
2493349cc55cSDimitry Andric 
249481ad6265SDimitry Andric   VPBaseLoadStoreSDNode(ISD::NodeType NodeTy, unsigned Order,
249581ad6265SDimitry Andric                         const DebugLoc &DL, SDVTList VTs,
249681ad6265SDimitry Andric                         ISD::MemIndexedMode AM, EVT MemVT,
2497349cc55cSDimitry Andric                         MachineMemOperand *MMO)
249881ad6265SDimitry Andric       : MemSDNode(NodeTy, Order, DL, VTs, MemVT, MMO) {
2499349cc55cSDimitry Andric     LSBaseSDNodeBits.AddressingMode = AM;
2500349cc55cSDimitry Andric     assert(getAddressingMode() == AM && "Value truncated");
2501349cc55cSDimitry Andric   }
2502349cc55cSDimitry Andric 
250381ad6265SDimitry Andric   // VPStridedStoreSDNode (Chain, Data, Ptr,    Offset, Stride, Mask, EVL)
2504349cc55cSDimitry Andric   // VPStoreSDNode        (Chain, Data, Ptr,    Offset, Mask,   EVL)
250581ad6265SDimitry Andric   // VPStridedLoadSDNode  (Chain, Ptr,  Offset, Stride, Mask,   EVL)
250681ad6265SDimitry Andric   // VPLoadSDNode         (Chain, Ptr,  Offset, Mask,   EVL)
2507349cc55cSDimitry Andric   // Mask is a vector of i1 elements;
2508349cc55cSDimitry Andric   // the type of EVL is TLI.getVPExplicitVectorLengthTy().
2509349cc55cSDimitry Andric   const SDValue &getOffset() const {
251081ad6265SDimitry Andric     return getOperand((getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_LOAD ||
251181ad6265SDimitry Andric                        getOpcode() == ISD::VP_LOAD)
251281ad6265SDimitry Andric                           ? 2
251381ad6265SDimitry Andric                           : 3);
2514349cc55cSDimitry Andric   }
2515349cc55cSDimitry Andric   const SDValue &getBasePtr() const {
251681ad6265SDimitry Andric     return getOperand((getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_LOAD ||
251781ad6265SDimitry Andric                        getOpcode() == ISD::VP_LOAD)
251881ad6265SDimitry Andric                           ? 1
251981ad6265SDimitry Andric                           : 2);
2520349cc55cSDimitry Andric   }
2521349cc55cSDimitry Andric   const SDValue &getMask() const {
252281ad6265SDimitry Andric     switch (getOpcode()) {
252381ad6265SDimitry Andric     default:
252481ad6265SDimitry Andric       llvm_unreachable("Invalid opcode");
252581ad6265SDimitry Andric     case ISD::VP_LOAD:
252681ad6265SDimitry Andric       return getOperand(3);
252781ad6265SDimitry Andric     case ISD::VP_STORE:
252881ad6265SDimitry Andric     case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
252981ad6265SDimitry Andric       return getOperand(4);
253081ad6265SDimitry Andric     case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
253181ad6265SDimitry Andric       return getOperand(5);
253281ad6265SDimitry Andric     }
2533349cc55cSDimitry Andric   }
2534349cc55cSDimitry Andric   const SDValue &getVectorLength() const {
253581ad6265SDimitry Andric     switch (getOpcode()) {
253681ad6265SDimitry Andric     default:
253781ad6265SDimitry Andric       llvm_unreachable("Invalid opcode");
253881ad6265SDimitry Andric     case ISD::VP_LOAD:
253981ad6265SDimitry Andric       return getOperand(4);
254081ad6265SDimitry Andric     case ISD::VP_STORE:
254181ad6265SDimitry Andric     case ISD::EXPERIMENTAL_VP_STRIDED_LOAD:
254281ad6265SDimitry Andric       return getOperand(5);
254381ad6265SDimitry Andric     case ISD::EXPERIMENTAL_VP_STRIDED_STORE:
254481ad6265SDimitry Andric       return getOperand(6);
254581ad6265SDimitry Andric     }
2546349cc55cSDimitry Andric   }
2547349cc55cSDimitry Andric 
2548349cc55cSDimitry Andric   /// Return the addressing mode for this load or store:
2549349cc55cSDimitry Andric   /// unindexed, pre-inc, pre-dec, post-inc, or post-dec.
2550349cc55cSDimitry Andric   ISD::MemIndexedMode getAddressingMode() const {
2551349cc55cSDimitry Andric     return static_cast<ISD::MemIndexedMode>(LSBaseSDNodeBits.AddressingMode);
2552349cc55cSDimitry Andric   }
2553349cc55cSDimitry Andric 
2554349cc55cSDimitry Andric   /// Return true if this is a pre/post inc/dec load/store.
2555349cc55cSDimitry Andric   bool isIndexed() const { return getAddressingMode() != ISD::UNINDEXED; }
2556349cc55cSDimitry Andric 
2557349cc55cSDimitry Andric   /// Return true if this is NOT a pre/post inc/dec load/store.
2558349cc55cSDimitry Andric   bool isUnindexed() const { return getAddressingMode() == ISD::UNINDEXED; }
2559349cc55cSDimitry Andric 
2560349cc55cSDimitry Andric   static bool classof(const SDNode *N) {
256181ad6265SDimitry Andric     return N->getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_LOAD ||
256281ad6265SDimitry Andric            N->getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_STORE ||
256381ad6265SDimitry Andric            N->getOpcode() == ISD::VP_LOAD || N->getOpcode() == ISD::VP_STORE;
2564349cc55cSDimitry Andric   }
2565349cc55cSDimitry Andric };
2566349cc55cSDimitry Andric 
2567349cc55cSDimitry Andric /// This class is used to represent a VP_LOAD node
256881ad6265SDimitry Andric class VPLoadSDNode : public VPBaseLoadStoreSDNode {
2569349cc55cSDimitry Andric public:
2570349cc55cSDimitry Andric   friend class SelectionDAG;
2571349cc55cSDimitry Andric 
2572349cc55cSDimitry Andric   VPLoadSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
2573349cc55cSDimitry Andric                ISD::MemIndexedMode AM, ISD::LoadExtType ETy, bool isExpanding,
2574349cc55cSDimitry Andric                EVT MemVT, MachineMemOperand *MMO)
257581ad6265SDimitry Andric       : VPBaseLoadStoreSDNode(ISD::VP_LOAD, Order, dl, VTs, AM, MemVT, MMO) {
2576349cc55cSDimitry Andric     LoadSDNodeBits.ExtTy = ETy;
2577349cc55cSDimitry Andric     LoadSDNodeBits.IsExpanding = isExpanding;
2578349cc55cSDimitry Andric   }
2579349cc55cSDimitry Andric 
2580349cc55cSDimitry Andric   ISD::LoadExtType getExtensionType() const {
2581349cc55cSDimitry Andric     return static_cast<ISD::LoadExtType>(LoadSDNodeBits.ExtTy);
2582349cc55cSDimitry Andric   }
2583349cc55cSDimitry Andric 
2584349cc55cSDimitry Andric   const SDValue &getBasePtr() const { return getOperand(1); }
2585349cc55cSDimitry Andric   const SDValue &getOffset() const { return getOperand(2); }
2586349cc55cSDimitry Andric   const SDValue &getMask() const { return getOperand(3); }
2587349cc55cSDimitry Andric   const SDValue &getVectorLength() const { return getOperand(4); }
2588349cc55cSDimitry Andric 
2589349cc55cSDimitry Andric   static bool classof(const SDNode *N) {
2590349cc55cSDimitry Andric     return N->getOpcode() == ISD::VP_LOAD;
2591349cc55cSDimitry Andric   }
2592349cc55cSDimitry Andric   bool isExpandingLoad() const { return LoadSDNodeBits.IsExpanding; }
2593349cc55cSDimitry Andric };
2594349cc55cSDimitry Andric 
259581ad6265SDimitry Andric /// This class is used to represent an EXPERIMENTAL_VP_STRIDED_LOAD node.
259681ad6265SDimitry Andric class VPStridedLoadSDNode : public VPBaseLoadStoreSDNode {
259781ad6265SDimitry Andric public:
259881ad6265SDimitry Andric   friend class SelectionDAG;
259981ad6265SDimitry Andric 
260081ad6265SDimitry Andric   VPStridedLoadSDNode(unsigned Order, const DebugLoc &DL, SDVTList VTs,
260181ad6265SDimitry Andric                       ISD::MemIndexedMode AM, ISD::LoadExtType ETy,
260281ad6265SDimitry Andric                       bool IsExpanding, EVT MemVT, MachineMemOperand *MMO)
260381ad6265SDimitry Andric       : VPBaseLoadStoreSDNode(ISD::EXPERIMENTAL_VP_STRIDED_LOAD, Order, DL, VTs,
260481ad6265SDimitry Andric                               AM, MemVT, MMO) {
260581ad6265SDimitry Andric     LoadSDNodeBits.ExtTy = ETy;
260681ad6265SDimitry Andric     LoadSDNodeBits.IsExpanding = IsExpanding;
260781ad6265SDimitry Andric   }
260881ad6265SDimitry Andric 
260981ad6265SDimitry Andric   ISD::LoadExtType getExtensionType() const {
261081ad6265SDimitry Andric     return static_cast<ISD::LoadExtType>(LoadSDNodeBits.ExtTy);
261181ad6265SDimitry Andric   }
261281ad6265SDimitry Andric 
261381ad6265SDimitry Andric   const SDValue &getBasePtr() const { return getOperand(1); }
261481ad6265SDimitry Andric   const SDValue &getOffset() const { return getOperand(2); }
261581ad6265SDimitry Andric   const SDValue &getStride() const { return getOperand(3); }
261681ad6265SDimitry Andric   const SDValue &getMask() const { return getOperand(4); }
261781ad6265SDimitry Andric   const SDValue &getVectorLength() const { return getOperand(5); }
261881ad6265SDimitry Andric 
261981ad6265SDimitry Andric   static bool classof(const SDNode *N) {
262081ad6265SDimitry Andric     return N->getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_LOAD;
262181ad6265SDimitry Andric   }
262281ad6265SDimitry Andric   bool isExpandingLoad() const { return LoadSDNodeBits.IsExpanding; }
262381ad6265SDimitry Andric };
262481ad6265SDimitry Andric 
2625349cc55cSDimitry Andric /// This class is used to represent a VP_STORE node
262681ad6265SDimitry Andric class VPStoreSDNode : public VPBaseLoadStoreSDNode {
2627349cc55cSDimitry Andric public:
2628349cc55cSDimitry Andric   friend class SelectionDAG;
2629349cc55cSDimitry Andric 
2630349cc55cSDimitry Andric   VPStoreSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
2631349cc55cSDimitry Andric                 ISD::MemIndexedMode AM, bool isTrunc, bool isCompressing,
2632349cc55cSDimitry Andric                 EVT MemVT, MachineMemOperand *MMO)
263381ad6265SDimitry Andric       : VPBaseLoadStoreSDNode(ISD::VP_STORE, Order, dl, VTs, AM, MemVT, MMO) {
2634349cc55cSDimitry Andric     StoreSDNodeBits.IsTruncating = isTrunc;
2635349cc55cSDimitry Andric     StoreSDNodeBits.IsCompressing = isCompressing;
2636349cc55cSDimitry Andric   }
2637349cc55cSDimitry Andric 
2638349cc55cSDimitry Andric   /// Return true if this is a truncating store.
2639349cc55cSDimitry Andric   /// For integers this is the same as doing a TRUNCATE and storing the result.
2640349cc55cSDimitry Andric   /// For floats, it is the same as doing an FP_ROUND and storing the result.
2641349cc55cSDimitry Andric   bool isTruncatingStore() const { return StoreSDNodeBits.IsTruncating; }
2642349cc55cSDimitry Andric 
2643349cc55cSDimitry Andric   /// Returns true if the op does a compression to the vector before storing.
2644349cc55cSDimitry Andric   /// The node contiguously stores the active elements (integers or floats)
2645349cc55cSDimitry Andric   /// in src (those with their respective bit set in writemask k) to unaligned
2646349cc55cSDimitry Andric   /// memory at base_addr.
2647349cc55cSDimitry Andric   bool isCompressingStore() const { return StoreSDNodeBits.IsCompressing; }
2648349cc55cSDimitry Andric 
2649349cc55cSDimitry Andric   const SDValue &getValue() const { return getOperand(1); }
2650349cc55cSDimitry Andric   const SDValue &getBasePtr() const { return getOperand(2); }
2651349cc55cSDimitry Andric   const SDValue &getOffset() const { return getOperand(3); }
2652349cc55cSDimitry Andric   const SDValue &getMask() const { return getOperand(4); }
2653349cc55cSDimitry Andric   const SDValue &getVectorLength() const { return getOperand(5); }
2654349cc55cSDimitry Andric 
2655349cc55cSDimitry Andric   static bool classof(const SDNode *N) {
2656349cc55cSDimitry Andric     return N->getOpcode() == ISD::VP_STORE;
2657349cc55cSDimitry Andric   }
2658349cc55cSDimitry Andric };
2659349cc55cSDimitry Andric 
266081ad6265SDimitry Andric /// This class is used to represent an EXPERIMENTAL_VP_STRIDED_STORE node.
266181ad6265SDimitry Andric class VPStridedStoreSDNode : public VPBaseLoadStoreSDNode {
266281ad6265SDimitry Andric public:
266381ad6265SDimitry Andric   friend class SelectionDAG;
266481ad6265SDimitry Andric 
266581ad6265SDimitry Andric   VPStridedStoreSDNode(unsigned Order, const DebugLoc &DL, SDVTList VTs,
266681ad6265SDimitry Andric                        ISD::MemIndexedMode AM, bool IsTrunc, bool IsCompressing,
266781ad6265SDimitry Andric                        EVT MemVT, MachineMemOperand *MMO)
266881ad6265SDimitry Andric       : VPBaseLoadStoreSDNode(ISD::EXPERIMENTAL_VP_STRIDED_STORE, Order, DL,
266981ad6265SDimitry Andric                               VTs, AM, MemVT, MMO) {
267081ad6265SDimitry Andric     StoreSDNodeBits.IsTruncating = IsTrunc;
267181ad6265SDimitry Andric     StoreSDNodeBits.IsCompressing = IsCompressing;
267281ad6265SDimitry Andric   }
267381ad6265SDimitry Andric 
267481ad6265SDimitry Andric   /// Return true if this is a truncating store.
267581ad6265SDimitry Andric   /// For integers this is the same as doing a TRUNCATE and storing the result.
267681ad6265SDimitry Andric   /// For floats, it is the same as doing an FP_ROUND and storing the result.
267781ad6265SDimitry Andric   bool isTruncatingStore() const { return StoreSDNodeBits.IsTruncating; }
267881ad6265SDimitry Andric 
267981ad6265SDimitry Andric   /// Returns true if the op does a compression to the vector before storing.
268081ad6265SDimitry Andric   /// The node contiguously stores the active elements (integers or floats)
268181ad6265SDimitry Andric   /// in src (those with their respective bit set in writemask k) to unaligned
268281ad6265SDimitry Andric   /// memory at base_addr.
268381ad6265SDimitry Andric   bool isCompressingStore() const { return StoreSDNodeBits.IsCompressing; }
268481ad6265SDimitry Andric 
268581ad6265SDimitry Andric   const SDValue &getValue() const { return getOperand(1); }
268681ad6265SDimitry Andric   const SDValue &getBasePtr() const { return getOperand(2); }
268781ad6265SDimitry Andric   const SDValue &getOffset() const { return getOperand(3); }
268881ad6265SDimitry Andric   const SDValue &getStride() const { return getOperand(4); }
268981ad6265SDimitry Andric   const SDValue &getMask() const { return getOperand(5); }
269081ad6265SDimitry Andric   const SDValue &getVectorLength() const { return getOperand(6); }
269181ad6265SDimitry Andric 
269281ad6265SDimitry Andric   static bool classof(const SDNode *N) {
269381ad6265SDimitry Andric     return N->getOpcode() == ISD::EXPERIMENTAL_VP_STRIDED_STORE;
269481ad6265SDimitry Andric   }
269581ad6265SDimitry Andric };
269681ad6265SDimitry Andric 
26970b57cec5SDimitry Andric /// This base class is used to represent MLOAD and MSTORE nodes
26980b57cec5SDimitry Andric class MaskedLoadStoreSDNode : public MemSDNode {
26990b57cec5SDimitry Andric public:
27000b57cec5SDimitry Andric   friend class SelectionDAG;
27010b57cec5SDimitry Andric 
27020b57cec5SDimitry Andric   MaskedLoadStoreSDNode(ISD::NodeType NodeTy, unsigned Order,
2703480093f4SDimitry Andric                         const DebugLoc &dl, SDVTList VTs,
2704480093f4SDimitry Andric                         ISD::MemIndexedMode AM, EVT MemVT,
27050b57cec5SDimitry Andric                         MachineMemOperand *MMO)
2706480093f4SDimitry Andric       : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {
2707480093f4SDimitry Andric     LSBaseSDNodeBits.AddressingMode = AM;
2708480093f4SDimitry Andric     assert(getAddressingMode() == AM && "Value truncated");
2709480093f4SDimitry Andric   }
27100b57cec5SDimitry Andric 
2711480093f4SDimitry Andric   // MaskedLoadSDNode (Chain, ptr, offset, mask, passthru)
2712480093f4SDimitry Andric   // MaskedStoreSDNode (Chain, data, ptr, offset, mask)
27130b57cec5SDimitry Andric   // Mask is a vector of i1 elements
2714480093f4SDimitry Andric   const SDValue &getOffset() const {
27150b57cec5SDimitry Andric     return getOperand(getOpcode() == ISD::MLOAD ? 2 : 3);
27160b57cec5SDimitry Andric   }
2717480093f4SDimitry Andric   const SDValue &getMask() const {
2718480093f4SDimitry Andric     return getOperand(getOpcode() == ISD::MLOAD ? 3 : 4);
2719480093f4SDimitry Andric   }
2720480093f4SDimitry Andric 
2721480093f4SDimitry Andric   /// Return the addressing mode for this load or store:
2722480093f4SDimitry Andric   /// unindexed, pre-inc, pre-dec, post-inc, or post-dec.
2723480093f4SDimitry Andric   ISD::MemIndexedMode getAddressingMode() const {
2724480093f4SDimitry Andric     return static_cast<ISD::MemIndexedMode>(LSBaseSDNodeBits.AddressingMode);
2725480093f4SDimitry Andric   }
2726480093f4SDimitry Andric 
2727480093f4SDimitry Andric   /// Return true if this is a pre/post inc/dec load/store.
2728480093f4SDimitry Andric   bool isIndexed() const { return getAddressingMode() != ISD::UNINDEXED; }
2729480093f4SDimitry Andric 
2730480093f4SDimitry Andric   /// Return true if this is NOT a pre/post inc/dec load/store.
2731480093f4SDimitry Andric   bool isUnindexed() const { return getAddressingMode() == ISD::UNINDEXED; }
27320b57cec5SDimitry Andric 
27330b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
27340b57cec5SDimitry Andric     return N->getOpcode() == ISD::MLOAD ||
27350b57cec5SDimitry Andric            N->getOpcode() == ISD::MSTORE;
27360b57cec5SDimitry Andric   }
27370b57cec5SDimitry Andric };
27380b57cec5SDimitry Andric 
27390b57cec5SDimitry Andric /// This class is used to represent an MLOAD node
27400b57cec5SDimitry Andric class MaskedLoadSDNode : public MaskedLoadStoreSDNode {
27410b57cec5SDimitry Andric public:
27420b57cec5SDimitry Andric   friend class SelectionDAG;
27430b57cec5SDimitry Andric 
27440b57cec5SDimitry Andric   MaskedLoadSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
2745480093f4SDimitry Andric                    ISD::MemIndexedMode AM, ISD::LoadExtType ETy,
2746480093f4SDimitry Andric                    bool IsExpanding, EVT MemVT, MachineMemOperand *MMO)
2747480093f4SDimitry Andric       : MaskedLoadStoreSDNode(ISD::MLOAD, Order, dl, VTs, AM, MemVT, MMO) {
27480b57cec5SDimitry Andric     LoadSDNodeBits.ExtTy = ETy;
27490b57cec5SDimitry Andric     LoadSDNodeBits.IsExpanding = IsExpanding;
27500b57cec5SDimitry Andric   }
27510b57cec5SDimitry Andric 
27520b57cec5SDimitry Andric   ISD::LoadExtType getExtensionType() const {
27530b57cec5SDimitry Andric     return static_cast<ISD::LoadExtType>(LoadSDNodeBits.ExtTy);
27540b57cec5SDimitry Andric   }
27550b57cec5SDimitry Andric 
27560b57cec5SDimitry Andric   const SDValue &getBasePtr() const { return getOperand(1); }
2757480093f4SDimitry Andric   const SDValue &getOffset() const { return getOperand(2); }
2758480093f4SDimitry Andric   const SDValue &getMask() const { return getOperand(3); }
2759480093f4SDimitry Andric   const SDValue &getPassThru() const { return getOperand(4); }
27600b57cec5SDimitry Andric 
27610b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
27620b57cec5SDimitry Andric     return N->getOpcode() == ISD::MLOAD;
27630b57cec5SDimitry Andric   }
27640b57cec5SDimitry Andric 
27650b57cec5SDimitry Andric   bool isExpandingLoad() const { return LoadSDNodeBits.IsExpanding; }
27660b57cec5SDimitry Andric };
27670b57cec5SDimitry Andric 
27680b57cec5SDimitry Andric /// This class is used to represent an MSTORE node
27690b57cec5SDimitry Andric class MaskedStoreSDNode : public MaskedLoadStoreSDNode {
27700b57cec5SDimitry Andric public:
27710b57cec5SDimitry Andric   friend class SelectionDAG;
27720b57cec5SDimitry Andric 
27730b57cec5SDimitry Andric   MaskedStoreSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
2774480093f4SDimitry Andric                     ISD::MemIndexedMode AM, bool isTrunc, bool isCompressing,
2775480093f4SDimitry Andric                     EVT MemVT, MachineMemOperand *MMO)
2776480093f4SDimitry Andric       : MaskedLoadStoreSDNode(ISD::MSTORE, Order, dl, VTs, AM, MemVT, MMO) {
27770b57cec5SDimitry Andric     StoreSDNodeBits.IsTruncating = isTrunc;
27780b57cec5SDimitry Andric     StoreSDNodeBits.IsCompressing = isCompressing;
27790b57cec5SDimitry Andric   }
27800b57cec5SDimitry Andric 
27810b57cec5SDimitry Andric   /// Return true if the op does a truncation before store.
27820b57cec5SDimitry Andric   /// For integers this is the same as doing a TRUNCATE and storing the result.
27830b57cec5SDimitry Andric   /// For floats, it is the same as doing an FP_ROUND and storing the result.
27840b57cec5SDimitry Andric   bool isTruncatingStore() const { return StoreSDNodeBits.IsTruncating; }
27850b57cec5SDimitry Andric 
27860b57cec5SDimitry Andric   /// Returns true if the op does a compression to the vector before storing.
27870b57cec5SDimitry Andric   /// The node contiguously stores the active elements (integers or floats)
27880b57cec5SDimitry Andric   /// in src (those with their respective bit set in writemask k) to unaligned
27890b57cec5SDimitry Andric   /// memory at base_addr.
27900b57cec5SDimitry Andric   bool isCompressingStore() const { return StoreSDNodeBits.IsCompressing; }
27910b57cec5SDimitry Andric 
27920b57cec5SDimitry Andric   const SDValue &getValue() const { return getOperand(1); }
27930b57cec5SDimitry Andric   const SDValue &getBasePtr() const { return getOperand(2); }
2794480093f4SDimitry Andric   const SDValue &getOffset() const { return getOperand(3); }
2795480093f4SDimitry Andric   const SDValue &getMask() const { return getOperand(4); }
27960b57cec5SDimitry Andric 
27970b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
27980b57cec5SDimitry Andric     return N->getOpcode() == ISD::MSTORE;
27990b57cec5SDimitry Andric   }
28000b57cec5SDimitry Andric };
28010b57cec5SDimitry Andric 
28020b57cec5SDimitry Andric /// This is a base class used to represent
2803349cc55cSDimitry Andric /// VP_GATHER and VP_SCATTER nodes
2804349cc55cSDimitry Andric ///
2805349cc55cSDimitry Andric class VPGatherScatterSDNode : public MemSDNode {
2806349cc55cSDimitry Andric public:
2807349cc55cSDimitry Andric   friend class SelectionDAG;
2808349cc55cSDimitry Andric 
2809349cc55cSDimitry Andric   VPGatherScatterSDNode(ISD::NodeType NodeTy, unsigned Order,
2810349cc55cSDimitry Andric                         const DebugLoc &dl, SDVTList VTs, EVT MemVT,
2811349cc55cSDimitry Andric                         MachineMemOperand *MMO, ISD::MemIndexType IndexType)
2812349cc55cSDimitry Andric       : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {
2813349cc55cSDimitry Andric     LSBaseSDNodeBits.AddressingMode = IndexType;
2814349cc55cSDimitry Andric     assert(getIndexType() == IndexType && "Value truncated");
2815349cc55cSDimitry Andric   }
2816349cc55cSDimitry Andric 
2817349cc55cSDimitry Andric   /// How is Index applied to BasePtr when computing addresses.
2818349cc55cSDimitry Andric   ISD::MemIndexType getIndexType() const {
2819349cc55cSDimitry Andric     return static_cast<ISD::MemIndexType>(LSBaseSDNodeBits.AddressingMode);
2820349cc55cSDimitry Andric   }
2821349cc55cSDimitry Andric   bool isIndexScaled() const {
282281ad6265SDimitry Andric     return !cast<ConstantSDNode>(getScale())->isOne();
2823349cc55cSDimitry Andric   }
282481ad6265SDimitry Andric   bool isIndexSigned() const { return isIndexTypeSigned(getIndexType()); }
2825349cc55cSDimitry Andric 
2826349cc55cSDimitry Andric   // In the both nodes address is Op1, mask is Op2:
2827349cc55cSDimitry Andric   // VPGatherSDNode  (Chain, base, index, scale, mask, vlen)
2828349cc55cSDimitry Andric   // VPScatterSDNode (Chain, value, base, index, scale, mask, vlen)
2829349cc55cSDimitry Andric   // Mask is a vector of i1 elements
2830349cc55cSDimitry Andric   const SDValue &getBasePtr() const {
2831349cc55cSDimitry Andric     return getOperand((getOpcode() == ISD::VP_GATHER) ? 1 : 2);
2832349cc55cSDimitry Andric   }
2833349cc55cSDimitry Andric   const SDValue &getIndex() const {
2834349cc55cSDimitry Andric     return getOperand((getOpcode() == ISD::VP_GATHER) ? 2 : 3);
2835349cc55cSDimitry Andric   }
2836349cc55cSDimitry Andric   const SDValue &getScale() const {
2837349cc55cSDimitry Andric     return getOperand((getOpcode() == ISD::VP_GATHER) ? 3 : 4);
2838349cc55cSDimitry Andric   }
2839349cc55cSDimitry Andric   const SDValue &getMask() const {
2840349cc55cSDimitry Andric     return getOperand((getOpcode() == ISD::VP_GATHER) ? 4 : 5);
2841349cc55cSDimitry Andric   }
2842349cc55cSDimitry Andric   const SDValue &getVectorLength() const {
2843349cc55cSDimitry Andric     return getOperand((getOpcode() == ISD::VP_GATHER) ? 5 : 6);
2844349cc55cSDimitry Andric   }
2845349cc55cSDimitry Andric 
2846349cc55cSDimitry Andric   static bool classof(const SDNode *N) {
2847349cc55cSDimitry Andric     return N->getOpcode() == ISD::VP_GATHER ||
2848349cc55cSDimitry Andric            N->getOpcode() == ISD::VP_SCATTER;
2849349cc55cSDimitry Andric   }
2850349cc55cSDimitry Andric };
2851349cc55cSDimitry Andric 
2852349cc55cSDimitry Andric /// This class is used to represent an VP_GATHER node
2853349cc55cSDimitry Andric ///
2854349cc55cSDimitry Andric class VPGatherSDNode : public VPGatherScatterSDNode {
2855349cc55cSDimitry Andric public:
2856349cc55cSDimitry Andric   friend class SelectionDAG;
2857349cc55cSDimitry Andric 
2858349cc55cSDimitry Andric   VPGatherSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, EVT MemVT,
2859349cc55cSDimitry Andric                  MachineMemOperand *MMO, ISD::MemIndexType IndexType)
2860349cc55cSDimitry Andric       : VPGatherScatterSDNode(ISD::VP_GATHER, Order, dl, VTs, MemVT, MMO,
2861349cc55cSDimitry Andric                               IndexType) {}
2862349cc55cSDimitry Andric 
2863349cc55cSDimitry Andric   static bool classof(const SDNode *N) {
2864349cc55cSDimitry Andric     return N->getOpcode() == ISD::VP_GATHER;
2865349cc55cSDimitry Andric   }
2866349cc55cSDimitry Andric };
2867349cc55cSDimitry Andric 
2868349cc55cSDimitry Andric /// This class is used to represent an VP_SCATTER node
2869349cc55cSDimitry Andric ///
2870349cc55cSDimitry Andric class VPScatterSDNode : public VPGatherScatterSDNode {
2871349cc55cSDimitry Andric public:
2872349cc55cSDimitry Andric   friend class SelectionDAG;
2873349cc55cSDimitry Andric 
2874349cc55cSDimitry Andric   VPScatterSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs, EVT MemVT,
2875349cc55cSDimitry Andric                   MachineMemOperand *MMO, ISD::MemIndexType IndexType)
2876349cc55cSDimitry Andric       : VPGatherScatterSDNode(ISD::VP_SCATTER, Order, dl, VTs, MemVT, MMO,
2877349cc55cSDimitry Andric                               IndexType) {}
2878349cc55cSDimitry Andric 
2879349cc55cSDimitry Andric   const SDValue &getValue() const { return getOperand(1); }
2880349cc55cSDimitry Andric 
2881349cc55cSDimitry Andric   static bool classof(const SDNode *N) {
2882349cc55cSDimitry Andric     return N->getOpcode() == ISD::VP_SCATTER;
2883349cc55cSDimitry Andric   }
2884349cc55cSDimitry Andric };
2885349cc55cSDimitry Andric 
2886349cc55cSDimitry Andric /// This is a base class used to represent
28870b57cec5SDimitry Andric /// MGATHER and MSCATTER nodes
28880b57cec5SDimitry Andric ///
28890b57cec5SDimitry Andric class MaskedGatherScatterSDNode : public MemSDNode {
28900b57cec5SDimitry Andric public:
28910b57cec5SDimitry Andric   friend class SelectionDAG;
28920b57cec5SDimitry Andric 
28930b57cec5SDimitry Andric   MaskedGatherScatterSDNode(ISD::NodeType NodeTy, unsigned Order,
28940b57cec5SDimitry Andric                             const DebugLoc &dl, SDVTList VTs, EVT MemVT,
28958bcb0991SDimitry Andric                             MachineMemOperand *MMO, ISD::MemIndexType IndexType)
28968bcb0991SDimitry Andric       : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {
28978bcb0991SDimitry Andric     LSBaseSDNodeBits.AddressingMode = IndexType;
28988bcb0991SDimitry Andric     assert(getIndexType() == IndexType && "Value truncated");
28998bcb0991SDimitry Andric   }
29008bcb0991SDimitry Andric 
29018bcb0991SDimitry Andric   /// How is Index applied to BasePtr when computing addresses.
29028bcb0991SDimitry Andric   ISD::MemIndexType getIndexType() const {
29038bcb0991SDimitry Andric     return static_cast<ISD::MemIndexType>(LSBaseSDNodeBits.AddressingMode);
29048bcb0991SDimitry Andric   }
29058bcb0991SDimitry Andric   bool isIndexScaled() const {
290681ad6265SDimitry Andric     return !cast<ConstantSDNode>(getScale())->isOne();
29078bcb0991SDimitry Andric   }
290881ad6265SDimitry Andric   bool isIndexSigned() const { return isIndexTypeSigned(getIndexType()); }
29090b57cec5SDimitry Andric 
29100b57cec5SDimitry Andric   // In the both nodes address is Op1, mask is Op2:
29110b57cec5SDimitry Andric   // MaskedGatherSDNode  (Chain, passthru, mask, base, index, scale)
29120b57cec5SDimitry Andric   // MaskedScatterSDNode (Chain, value, mask, base, index, scale)
29130b57cec5SDimitry Andric   // Mask is a vector of i1 elements
29140b57cec5SDimitry Andric   const SDValue &getBasePtr() const { return getOperand(3); }
29150b57cec5SDimitry Andric   const SDValue &getIndex()   const { return getOperand(4); }
29160b57cec5SDimitry Andric   const SDValue &getMask()    const { return getOperand(2); }
29170b57cec5SDimitry Andric   const SDValue &getScale()   const { return getOperand(5); }
29180b57cec5SDimitry Andric 
29190b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
29200b57cec5SDimitry Andric     return N->getOpcode() == ISD::MGATHER ||
29210b57cec5SDimitry Andric            N->getOpcode() == ISD::MSCATTER;
29220b57cec5SDimitry Andric   }
29230b57cec5SDimitry Andric };
29240b57cec5SDimitry Andric 
29250b57cec5SDimitry Andric /// This class is used to represent an MGATHER node
29260b57cec5SDimitry Andric ///
29270b57cec5SDimitry Andric class MaskedGatherSDNode : public MaskedGatherScatterSDNode {
29280b57cec5SDimitry Andric public:
29290b57cec5SDimitry Andric   friend class SelectionDAG;
29300b57cec5SDimitry Andric 
29310b57cec5SDimitry Andric   MaskedGatherSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
29328bcb0991SDimitry Andric                      EVT MemVT, MachineMemOperand *MMO,
2933e8d8bef9SDimitry Andric                      ISD::MemIndexType IndexType, ISD::LoadExtType ETy)
29348bcb0991SDimitry Andric       : MaskedGatherScatterSDNode(ISD::MGATHER, Order, dl, VTs, MemVT, MMO,
2935e8d8bef9SDimitry Andric                                   IndexType) {
2936e8d8bef9SDimitry Andric     LoadSDNodeBits.ExtTy = ETy;
2937e8d8bef9SDimitry Andric   }
29380b57cec5SDimitry Andric 
29390b57cec5SDimitry Andric   const SDValue &getPassThru() const { return getOperand(1); }
29400b57cec5SDimitry Andric 
2941e8d8bef9SDimitry Andric   ISD::LoadExtType getExtensionType() const {
2942e8d8bef9SDimitry Andric     return ISD::LoadExtType(LoadSDNodeBits.ExtTy);
2943e8d8bef9SDimitry Andric   }
2944e8d8bef9SDimitry Andric 
29450b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
29460b57cec5SDimitry Andric     return N->getOpcode() == ISD::MGATHER;
29470b57cec5SDimitry Andric   }
29480b57cec5SDimitry Andric };
29490b57cec5SDimitry Andric 
29500b57cec5SDimitry Andric /// This class is used to represent an MSCATTER node
29510b57cec5SDimitry Andric ///
29520b57cec5SDimitry Andric class MaskedScatterSDNode : public MaskedGatherScatterSDNode {
29530b57cec5SDimitry Andric public:
29540b57cec5SDimitry Andric   friend class SelectionDAG;
29550b57cec5SDimitry Andric 
29560b57cec5SDimitry Andric   MaskedScatterSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
29578bcb0991SDimitry Andric                       EVT MemVT, MachineMemOperand *MMO,
2958e8d8bef9SDimitry Andric                       ISD::MemIndexType IndexType, bool IsTrunc)
29598bcb0991SDimitry Andric       : MaskedGatherScatterSDNode(ISD::MSCATTER, Order, dl, VTs, MemVT, MMO,
2960e8d8bef9SDimitry Andric                                   IndexType) {
2961e8d8bef9SDimitry Andric     StoreSDNodeBits.IsTruncating = IsTrunc;
2962e8d8bef9SDimitry Andric   }
2963e8d8bef9SDimitry Andric 
2964e8d8bef9SDimitry Andric   /// Return true if the op does a truncation before store.
2965e8d8bef9SDimitry Andric   /// For integers this is the same as doing a TRUNCATE and storing the result.
2966e8d8bef9SDimitry Andric   /// For floats, it is the same as doing an FP_ROUND and storing the result.
2967e8d8bef9SDimitry Andric   bool isTruncatingStore() const { return StoreSDNodeBits.IsTruncating; }
29680b57cec5SDimitry Andric 
29690b57cec5SDimitry Andric   const SDValue &getValue() const { return getOperand(1); }
29700b57cec5SDimitry Andric 
29710b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
29720b57cec5SDimitry Andric     return N->getOpcode() == ISD::MSCATTER;
29730b57cec5SDimitry Andric   }
29740b57cec5SDimitry Andric };
29750b57cec5SDimitry Andric 
2976*0fca6ea1SDimitry Andric class MaskedHistogramSDNode : public MemSDNode {
2977*0fca6ea1SDimitry Andric public:
2978*0fca6ea1SDimitry Andric   friend class SelectionDAG;
2979*0fca6ea1SDimitry Andric 
2980*0fca6ea1SDimitry Andric   MaskedHistogramSDNode(unsigned Order, const DebugLoc &DL, SDVTList VTs,
2981*0fca6ea1SDimitry Andric                         EVT MemVT, MachineMemOperand *MMO,
2982*0fca6ea1SDimitry Andric                         ISD::MemIndexType IndexType)
2983*0fca6ea1SDimitry Andric       : MemSDNode(ISD::EXPERIMENTAL_VECTOR_HISTOGRAM, Order, DL, VTs, MemVT,
2984*0fca6ea1SDimitry Andric                   MMO) {
2985*0fca6ea1SDimitry Andric     LSBaseSDNodeBits.AddressingMode = IndexType;
2986*0fca6ea1SDimitry Andric   }
2987*0fca6ea1SDimitry Andric 
2988*0fca6ea1SDimitry Andric   ISD::MemIndexType getIndexType() const {
2989*0fca6ea1SDimitry Andric     return static_cast<ISD::MemIndexType>(LSBaseSDNodeBits.AddressingMode);
2990*0fca6ea1SDimitry Andric   }
2991*0fca6ea1SDimitry Andric 
2992*0fca6ea1SDimitry Andric   const SDValue &getBasePtr() const { return getOperand(3); }
2993*0fca6ea1SDimitry Andric   const SDValue &getIndex() const { return getOperand(4); }
2994*0fca6ea1SDimitry Andric   const SDValue &getMask() const { return getOperand(2); }
2995*0fca6ea1SDimitry Andric   const SDValue &getScale() const { return getOperand(5); }
2996*0fca6ea1SDimitry Andric   const SDValue &getInc() const { return getOperand(1); }
2997*0fca6ea1SDimitry Andric   const SDValue &getIntID() const { return getOperand(6); }
2998*0fca6ea1SDimitry Andric 
2999*0fca6ea1SDimitry Andric   static bool classof(const SDNode *N) {
3000*0fca6ea1SDimitry Andric     return N->getOpcode() == ISD::EXPERIMENTAL_VECTOR_HISTOGRAM;
3001*0fca6ea1SDimitry Andric   }
3002*0fca6ea1SDimitry Andric };
3003*0fca6ea1SDimitry Andric 
300406c3fb27SDimitry Andric class FPStateAccessSDNode : public MemSDNode {
300506c3fb27SDimitry Andric public:
300606c3fb27SDimitry Andric   friend class SelectionDAG;
300706c3fb27SDimitry Andric 
300806c3fb27SDimitry Andric   FPStateAccessSDNode(unsigned NodeTy, unsigned Order, const DebugLoc &dl,
300906c3fb27SDimitry Andric                       SDVTList VTs, EVT MemVT, MachineMemOperand *MMO)
301006c3fb27SDimitry Andric       : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {
301106c3fb27SDimitry Andric     assert((NodeTy == ISD::GET_FPENV_MEM || NodeTy == ISD::SET_FPENV_MEM) &&
301206c3fb27SDimitry Andric            "Expected FP state access node");
301306c3fb27SDimitry Andric   }
301406c3fb27SDimitry Andric 
301506c3fb27SDimitry Andric   static bool classof(const SDNode *N) {
301606c3fb27SDimitry Andric     return N->getOpcode() == ISD::GET_FPENV_MEM ||
301706c3fb27SDimitry Andric            N->getOpcode() == ISD::SET_FPENV_MEM;
301806c3fb27SDimitry Andric   }
301906c3fb27SDimitry Andric };
302006c3fb27SDimitry Andric 
30210b57cec5SDimitry Andric /// An SDNode that represents everything that will be needed
30220b57cec5SDimitry Andric /// to construct a MachineInstr. These nodes are created during the
30230b57cec5SDimitry Andric /// instruction selection proper phase.
30240b57cec5SDimitry Andric ///
30250b57cec5SDimitry Andric /// Note that the only supported way to set the `memoperands` is by calling the
30260b57cec5SDimitry Andric /// `SelectionDAG::setNodeMemRefs` function as the memory management happens
30270b57cec5SDimitry Andric /// inside the DAG rather than in the node.
30280b57cec5SDimitry Andric class MachineSDNode : public SDNode {
30290b57cec5SDimitry Andric private:
30300b57cec5SDimitry Andric   friend class SelectionDAG;
30310b57cec5SDimitry Andric 
30320b57cec5SDimitry Andric   MachineSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL, SDVTList VTs)
30330b57cec5SDimitry Andric       : SDNode(Opc, Order, DL, VTs) {}
30340b57cec5SDimitry Andric 
30350b57cec5SDimitry Andric   // We use a pointer union between a single `MachineMemOperand` pointer and
30360b57cec5SDimitry Andric   // a pointer to an array of `MachineMemOperand` pointers. This is null when
30370b57cec5SDimitry Andric   // the number of these is zero, the single pointer variant used when the
30380b57cec5SDimitry Andric   // number is one, and the array is used for larger numbers.
30390b57cec5SDimitry Andric   //
30400b57cec5SDimitry Andric   // The array is allocated via the `SelectionDAG`'s allocator and so will
30410b57cec5SDimitry Andric   // always live until the DAG is cleaned up and doesn't require ownership here.
30420b57cec5SDimitry Andric   //
30430b57cec5SDimitry Andric   // We can't use something simpler like `TinyPtrVector` here because `SDNode`
30440b57cec5SDimitry Andric   // subclasses aren't managed in a conforming C++ manner. See the comments on
30450b57cec5SDimitry Andric   // `SelectionDAG::MorphNodeTo` which details what all goes on, but the
30460b57cec5SDimitry Andric   // constraint here is that these don't manage memory with their constructor or
30470b57cec5SDimitry Andric   // destructor and can be initialized to a good state even if they start off
30480b57cec5SDimitry Andric   // uninitialized.
30490b57cec5SDimitry Andric   PointerUnion<MachineMemOperand *, MachineMemOperand **> MemRefs = {};
30500b57cec5SDimitry Andric 
30510b57cec5SDimitry Andric   // Note that this could be folded into the above `MemRefs` member if doing so
30520b57cec5SDimitry Andric   // is advantageous at some point. We don't need to store this in most cases.
30530b57cec5SDimitry Andric   // However, at the moment this doesn't appear to make the allocation any
30540b57cec5SDimitry Andric   // smaller and makes the code somewhat simpler to read.
30550b57cec5SDimitry Andric   int NumMemRefs = 0;
30560b57cec5SDimitry Andric 
30570b57cec5SDimitry Andric public:
30580b57cec5SDimitry Andric   using mmo_iterator = ArrayRef<MachineMemOperand *>::const_iterator;
30590b57cec5SDimitry Andric 
30600b57cec5SDimitry Andric   ArrayRef<MachineMemOperand *> memoperands() const {
30610b57cec5SDimitry Andric     // Special case the common cases.
30620b57cec5SDimitry Andric     if (NumMemRefs == 0)
30630b57cec5SDimitry Andric       return {};
30640b57cec5SDimitry Andric     if (NumMemRefs == 1)
3065bdd1243dSDimitry Andric       return ArrayRef(MemRefs.getAddrOfPtr1(), 1);
30660b57cec5SDimitry Andric 
30670b57cec5SDimitry Andric     // Otherwise we have an actual array.
306806c3fb27SDimitry Andric     return ArrayRef(cast<MachineMemOperand **>(MemRefs), NumMemRefs);
30690b57cec5SDimitry Andric   }
30700b57cec5SDimitry Andric   mmo_iterator memoperands_begin() const { return memoperands().begin(); }
30710b57cec5SDimitry Andric   mmo_iterator memoperands_end() const { return memoperands().end(); }
30720b57cec5SDimitry Andric   bool memoperands_empty() const { return memoperands().empty(); }
30730b57cec5SDimitry Andric 
30740b57cec5SDimitry Andric   /// Clear out the memory reference descriptor list.
30750b57cec5SDimitry Andric   void clearMemRefs() {
30760b57cec5SDimitry Andric     MemRefs = nullptr;
30770b57cec5SDimitry Andric     NumMemRefs = 0;
30780b57cec5SDimitry Andric   }
30790b57cec5SDimitry Andric 
30800b57cec5SDimitry Andric   static bool classof(const SDNode *N) {
30810b57cec5SDimitry Andric     return N->isMachineOpcode();
30820b57cec5SDimitry Andric   }
30830b57cec5SDimitry Andric };
30840b57cec5SDimitry Andric 
30855ffd83dbSDimitry Andric /// An SDNode that records if a register contains a value that is guaranteed to
30865ffd83dbSDimitry Andric /// be aligned accordingly.
30875ffd83dbSDimitry Andric class AssertAlignSDNode : public SDNode {
30885ffd83dbSDimitry Andric   Align Alignment;
30895ffd83dbSDimitry Andric 
30905ffd83dbSDimitry Andric public:
3091*0fca6ea1SDimitry Andric   AssertAlignSDNode(unsigned Order, const DebugLoc &DL, SDVTList VTs, Align A)
3092*0fca6ea1SDimitry Andric       : SDNode(ISD::AssertAlign, Order, DL, VTs), Alignment(A) {}
30935ffd83dbSDimitry Andric 
30945ffd83dbSDimitry Andric   Align getAlign() const { return Alignment; }
30955ffd83dbSDimitry Andric 
30965ffd83dbSDimitry Andric   static bool classof(const SDNode *N) {
30975ffd83dbSDimitry Andric     return N->getOpcode() == ISD::AssertAlign;
30985ffd83dbSDimitry Andric   }
30995ffd83dbSDimitry Andric };
31005ffd83dbSDimitry Andric 
3101fe6060f1SDimitry Andric class SDNodeIterator {
31020b57cec5SDimitry Andric   const SDNode *Node;
31030b57cec5SDimitry Andric   unsigned Operand;
31040b57cec5SDimitry Andric 
31050b57cec5SDimitry Andric   SDNodeIterator(const SDNode *N, unsigned Op) : Node(N), Operand(Op) {}
31060b57cec5SDimitry Andric 
31070b57cec5SDimitry Andric public:
3108fe6060f1SDimitry Andric   using iterator_category = std::forward_iterator_tag;
3109fe6060f1SDimitry Andric   using value_type = SDNode;
3110fe6060f1SDimitry Andric   using difference_type = std::ptrdiff_t;
3111fe6060f1SDimitry Andric   using pointer = value_type *;
3112fe6060f1SDimitry Andric   using reference = value_type &;
3113fe6060f1SDimitry Andric 
31140b57cec5SDimitry Andric   bool operator==(const SDNodeIterator& x) const {
31150b57cec5SDimitry Andric     return Operand == x.Operand;
31160b57cec5SDimitry Andric   }
31170b57cec5SDimitry Andric   bool operator!=(const SDNodeIterator& x) const { return !operator==(x); }
31180b57cec5SDimitry Andric 
31190b57cec5SDimitry Andric   pointer operator*() const {
31200b57cec5SDimitry Andric     return Node->getOperand(Operand).getNode();
31210b57cec5SDimitry Andric   }
31220b57cec5SDimitry Andric   pointer operator->() const { return operator*(); }
31230b57cec5SDimitry Andric 
31240b57cec5SDimitry Andric   SDNodeIterator& operator++() {                // Preincrement
31250b57cec5SDimitry Andric     ++Operand;
31260b57cec5SDimitry Andric     return *this;
31270b57cec5SDimitry Andric   }
31280b57cec5SDimitry Andric   SDNodeIterator operator++(int) { // Postincrement
31290b57cec5SDimitry Andric     SDNodeIterator tmp = *this; ++*this; return tmp;
31300b57cec5SDimitry Andric   }
31310b57cec5SDimitry Andric   size_t operator-(SDNodeIterator Other) const {
31320b57cec5SDimitry Andric     assert(Node == Other.Node &&
31330b57cec5SDimitry Andric            "Cannot compare iterators of two different nodes!");
31340b57cec5SDimitry Andric     return Operand - Other.Operand;
31350b57cec5SDimitry Andric   }
31360b57cec5SDimitry Andric 
31370b57cec5SDimitry Andric   static SDNodeIterator begin(const SDNode *N) { return SDNodeIterator(N, 0); }
31380b57cec5SDimitry Andric   static SDNodeIterator end  (const SDNode *N) {
31390b57cec5SDimitry Andric     return SDNodeIterator(N, N->getNumOperands());
31400b57cec5SDimitry Andric   }
31410b57cec5SDimitry Andric 
31420b57cec5SDimitry Andric   unsigned getOperand() const { return Operand; }
31430b57cec5SDimitry Andric   const SDNode *getNode() const { return Node; }
31440b57cec5SDimitry Andric };
31450b57cec5SDimitry Andric 
31460b57cec5SDimitry Andric template <> struct GraphTraits<SDNode*> {
31470b57cec5SDimitry Andric   using NodeRef = SDNode *;
31480b57cec5SDimitry Andric   using ChildIteratorType = SDNodeIterator;
31490b57cec5SDimitry Andric 
31500b57cec5SDimitry Andric   static NodeRef getEntryNode(SDNode *N) { return N; }
31510b57cec5SDimitry Andric 
31520b57cec5SDimitry Andric   static ChildIteratorType child_begin(NodeRef N) {
31530b57cec5SDimitry Andric     return SDNodeIterator::begin(N);
31540b57cec5SDimitry Andric   }
31550b57cec5SDimitry Andric 
31560b57cec5SDimitry Andric   static ChildIteratorType child_end(NodeRef N) {
31570b57cec5SDimitry Andric     return SDNodeIterator::end(N);
31580b57cec5SDimitry Andric   }
31590b57cec5SDimitry Andric };
31600b57cec5SDimitry Andric 
31610b57cec5SDimitry Andric /// A representation of the largest SDNode, for use in sizeof().
31620b57cec5SDimitry Andric ///
31630b57cec5SDimitry Andric /// This needs to be a union because the largest node differs on 32 bit systems
31640b57cec5SDimitry Andric /// with 4 and 8 byte pointer alignment, respectively.
31650b57cec5SDimitry Andric using LargestSDNode = AlignedCharArrayUnion<AtomicSDNode, TargetIndexSDNode,
31660b57cec5SDimitry Andric                                             BlockAddressSDNode,
3167e8d8bef9SDimitry Andric                                             GlobalAddressSDNode,
3168e8d8bef9SDimitry Andric                                             PseudoProbeSDNode>;
31690b57cec5SDimitry Andric 
31700b57cec5SDimitry Andric /// The SDNode class with the greatest alignment requirement.
31710b57cec5SDimitry Andric using MostAlignedSDNode = GlobalAddressSDNode;
31720b57cec5SDimitry Andric 
31730b57cec5SDimitry Andric namespace ISD {
31740b57cec5SDimitry Andric 
31750b57cec5SDimitry Andric   /// Returns true if the specified node is a non-extending and unindexed load.
31760b57cec5SDimitry Andric   inline bool isNormalLoad(const SDNode *N) {
31775f757f3fSDimitry Andric     auto *Ld = dyn_cast<LoadSDNode>(N);
31780b57cec5SDimitry Andric     return Ld && Ld->getExtensionType() == ISD::NON_EXTLOAD &&
31790b57cec5SDimitry Andric            Ld->getAddressingMode() == ISD::UNINDEXED;
31800b57cec5SDimitry Andric   }
31810b57cec5SDimitry Andric 
31820b57cec5SDimitry Andric   /// Returns true if the specified node is a non-extending load.
31830b57cec5SDimitry Andric   inline bool isNON_EXTLoad(const SDNode *N) {
31845f757f3fSDimitry Andric     auto *Ld = dyn_cast<LoadSDNode>(N);
31855f757f3fSDimitry Andric     return Ld && Ld->getExtensionType() == ISD::NON_EXTLOAD;
31860b57cec5SDimitry Andric   }
31870b57cec5SDimitry Andric 
31880b57cec5SDimitry Andric   /// Returns true if the specified node is a EXTLOAD.
31890b57cec5SDimitry Andric   inline bool isEXTLoad(const SDNode *N) {
31905f757f3fSDimitry Andric     auto *Ld = dyn_cast<LoadSDNode>(N);
31915f757f3fSDimitry Andric     return Ld && Ld->getExtensionType() == ISD::EXTLOAD;
31920b57cec5SDimitry Andric   }
31930b57cec5SDimitry Andric 
31940b57cec5SDimitry Andric   /// Returns true if the specified node is a SEXTLOAD.
31950b57cec5SDimitry Andric   inline bool isSEXTLoad(const SDNode *N) {
31965f757f3fSDimitry Andric     auto *Ld = dyn_cast<LoadSDNode>(N);
31975f757f3fSDimitry Andric     return Ld && Ld->getExtensionType() == ISD::SEXTLOAD;
31980b57cec5SDimitry Andric   }
31990b57cec5SDimitry Andric 
32000b57cec5SDimitry Andric   /// Returns true if the specified node is a ZEXTLOAD.
32010b57cec5SDimitry Andric   inline bool isZEXTLoad(const SDNode *N) {
32025f757f3fSDimitry Andric     auto *Ld = dyn_cast<LoadSDNode>(N);
32035f757f3fSDimitry Andric     return Ld && Ld->getExtensionType() == ISD::ZEXTLOAD;
32040b57cec5SDimitry Andric   }
32050b57cec5SDimitry Andric 
32060b57cec5SDimitry Andric   /// Returns true if the specified node is an unindexed load.
32070b57cec5SDimitry Andric   inline bool isUNINDEXEDLoad(const SDNode *N) {
32085f757f3fSDimitry Andric     auto *Ld = dyn_cast<LoadSDNode>(N);
32095f757f3fSDimitry Andric     return Ld && Ld->getAddressingMode() == ISD::UNINDEXED;
32100b57cec5SDimitry Andric   }
32110b57cec5SDimitry Andric 
32120b57cec5SDimitry Andric   /// Returns true if the specified node is a non-truncating
32130b57cec5SDimitry Andric   /// and unindexed store.
32140b57cec5SDimitry Andric   inline bool isNormalStore(const SDNode *N) {
32155f757f3fSDimitry Andric     auto *St = dyn_cast<StoreSDNode>(N);
32160b57cec5SDimitry Andric     return St && !St->isTruncatingStore() &&
32170b57cec5SDimitry Andric            St->getAddressingMode() == ISD::UNINDEXED;
32180b57cec5SDimitry Andric   }
32190b57cec5SDimitry Andric 
32200b57cec5SDimitry Andric   /// Returns true if the specified node is an unindexed store.
32210b57cec5SDimitry Andric   inline bool isUNINDEXEDStore(const SDNode *N) {
32225f757f3fSDimitry Andric     auto *St = dyn_cast<StoreSDNode>(N);
32235f757f3fSDimitry Andric     return St && St->getAddressingMode() == ISD::UNINDEXED;
32240b57cec5SDimitry Andric   }
32250b57cec5SDimitry Andric 
32260b57cec5SDimitry Andric   /// Attempt to match a unary predicate against a scalar/splat constant or
32270b57cec5SDimitry Andric   /// every element of a constant BUILD_VECTOR.
32280b57cec5SDimitry Andric   /// If AllowUndef is true, then UNDEF elements will pass nullptr to Match.
32295f757f3fSDimitry Andric   template <typename ConstNodeType>
32305f757f3fSDimitry Andric   bool matchUnaryPredicateImpl(SDValue Op,
32315f757f3fSDimitry Andric                                std::function<bool(ConstNodeType *)> Match,
32320b57cec5SDimitry Andric                                bool AllowUndefs = false);
32330b57cec5SDimitry Andric 
32345f757f3fSDimitry Andric   /// Hook for matching ConstantSDNode predicate
32355f757f3fSDimitry Andric   inline bool matchUnaryPredicate(SDValue Op,
32365f757f3fSDimitry Andric                                   std::function<bool(ConstantSDNode *)> Match,
32375f757f3fSDimitry Andric                                   bool AllowUndefs = false) {
32385f757f3fSDimitry Andric     return matchUnaryPredicateImpl<ConstantSDNode>(Op, Match, AllowUndefs);
32395f757f3fSDimitry Andric   }
32405f757f3fSDimitry Andric 
32415f757f3fSDimitry Andric   /// Hook for matching ConstantFPSDNode predicate
32425f757f3fSDimitry Andric   inline bool
32435f757f3fSDimitry Andric   matchUnaryFpPredicate(SDValue Op,
32445f757f3fSDimitry Andric                         std::function<bool(ConstantFPSDNode *)> Match,
32455f757f3fSDimitry Andric                         bool AllowUndefs = false) {
32465f757f3fSDimitry Andric     return matchUnaryPredicateImpl<ConstantFPSDNode>(Op, Match, AllowUndefs);
32475f757f3fSDimitry Andric   }
32485f757f3fSDimitry Andric 
32490b57cec5SDimitry Andric   /// Attempt to match a binary predicate against a pair of scalar/splat
32500b57cec5SDimitry Andric   /// constants or every element of a pair of constant BUILD_VECTORs.
32510b57cec5SDimitry Andric   /// If AllowUndef is true, then UNDEF elements will pass nullptr to Match.
32520b57cec5SDimitry Andric   /// If AllowTypeMismatch is true then RetType + ArgTypes don't need to match.
32530b57cec5SDimitry Andric   bool matchBinaryPredicate(
32540b57cec5SDimitry Andric       SDValue LHS, SDValue RHS,
32550b57cec5SDimitry Andric       std::function<bool(ConstantSDNode *, ConstantSDNode *)> Match,
32560b57cec5SDimitry Andric       bool AllowUndefs = false, bool AllowTypeMismatch = false);
32575ffd83dbSDimitry Andric 
32585ffd83dbSDimitry Andric   /// Returns true if the specified value is the overflow result from one
32595ffd83dbSDimitry Andric   /// of the overflow intrinsic nodes.
32605ffd83dbSDimitry Andric   inline bool isOverflowIntrOpRes(SDValue Op) {
32615ffd83dbSDimitry Andric     unsigned Opc = Op.getOpcode();
32625ffd83dbSDimitry Andric     return (Op.getResNo() == 1 &&
32635ffd83dbSDimitry Andric             (Opc == ISD::SADDO || Opc == ISD::UADDO || Opc == ISD::SSUBO ||
32645ffd83dbSDimitry Andric              Opc == ISD::USUBO || Opc == ISD::SMULO || Opc == ISD::UMULO));
32655ffd83dbSDimitry Andric   }
32665ffd83dbSDimitry Andric 
32670b57cec5SDimitry Andric } // end namespace ISD
32680b57cec5SDimitry Andric 
32690b57cec5SDimitry Andric } // end namespace llvm
32700b57cec5SDimitry Andric 
32710b57cec5SDimitry Andric #endif // LLVM_CODEGEN_SELECTIONDAGNODES_H
3272