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