aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/CodeGen/SelectionDAGNodes.h
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-02 19:17:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-02 19:17:04 +0000
commitb915e9e0fc85ba6f398b3fab0db6a81a8913af94 (patch)
tree98b8f811c7aff2547cab8642daf372d6c59502fb /include/llvm/CodeGen/SelectionDAGNodes.h
parent6421cca32f69ac849537a3cff78c352195e99f1b (diff)
Notes
Diffstat (limited to 'include/llvm/CodeGen/SelectionDAGNodes.h')
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h450
1 files changed, 299 insertions, 151 deletions
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index cfcc4117f93b6..d4b7170eac3c5 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -19,23 +19,37 @@
#ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H
#define LLVM_CODEGEN_SELECTIONDAGNODES_H
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/GraphTraits.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineMemOperand.h"
+#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugLoc.h"
+#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
-#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/AtomicOrdering.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
#include <cassert>
+#include <climits>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <iterator>
+#include <string>
+#include <tuple>
namespace llvm {
@@ -44,12 +58,9 @@ class GlobalValue;
class MachineBasicBlock;
class MachineConstantPoolValue;
class SDNode;
-class HandleSDNode;
class Value;
class MCSymbol;
template <typename T> struct DenseMapInfo;
-template <typename T> struct simplify_type;
-template <typename T> struct ilist_traits;
void checkForCycles(const SDNode *N, const SelectionDAG *DAG = nullptr,
bool force = false);
@@ -64,6 +75,7 @@ struct SDVTList {
};
namespace ISD {
+
/// Node predicates
/// If N is a BUILD_VECTOR node whose elements are all the same constant or
@@ -89,7 +101,8 @@ namespace ISD {
/// Return true if the node has at least one operand and all operands of the
/// specified node are ISD::UNDEF.
bool allOperandsUndef(const SDNode *N);
-} // end llvm:ISD namespace
+
+} // end namespace ISD
//===----------------------------------------------------------------------===//
/// Unlike LLVM values, Selection DAG nodes may return multiple
@@ -107,6 +120,7 @@ class SDValue {
SDNode *Node; // The node defining the value we are using.
unsigned ResNo; // Which return value of the node we are using.
+
public:
SDValue() : Node(nullptr), ResNo(0) {}
SDValue(SDNode *node, unsigned resno);
@@ -188,29 +202,30 @@ public:
inline bool hasOneUse() const;
};
-
template<> struct DenseMapInfo<SDValue> {
static inline SDValue getEmptyKey() {
SDValue V;
V.ResNo = -1U;
return V;
}
+
static inline SDValue getTombstoneKey() {
SDValue V;
V.ResNo = -2U;
return V;
}
+
static unsigned getHashValue(const SDValue &Val) {
return ((unsigned)((uintptr_t)Val.getNode() >> 4) ^
(unsigned)((uintptr_t)Val.getNode() >> 9)) + Val.getResNo();
}
+
static bool isEqual(const SDValue &LHS, const SDValue &RHS) {
return LHS == RHS;
}
};
template <> struct isPodLike<SDValue> { static const bool value = true; };
-
/// Allow casting operators to work directly on
/// SDValues as if they were SDNode*'s.
template<> struct simplify_type<SDValue> {
@@ -244,7 +259,7 @@ class SDUse {
void operator=(const SDUse &U) = delete;
public:
- SDUse() : Val(), User(nullptr), Prev(nullptr), Next(nullptr) {}
+ SDUse() : User(nullptr), Prev(nullptr), Next(nullptr) {}
/// Normally SDUse will just implicitly convert to an SDValue that it holds.
operator const SDValue&() const { return Val; }
@@ -372,14 +387,6 @@ public:
bool hasAllowReciprocal() const { return AllowReciprocal; }
bool hasVectorReduction() const { return VectorReduction; }
- /// Return a raw encoding of the flags.
- /// This function should only be used to add data to the NodeID value.
- unsigned getRawFlags() const {
- return (NoUnsignedWrap << 0) | (NoSignedWrap << 1) | (Exact << 2) |
- (UnsafeAlgebra << 3) | (NoNaNs << 4) | (NoInfs << 5) |
- (NoSignedZeros << 6) | (AllowReciprocal << 7);
- }
-
/// Clear any flags in this flag set that aren't also set in Flags.
void intersectWith(const SDNodeFlags *Flags) {
NoUnsignedWrap &= Flags->NoUnsignedWrap;
@@ -400,15 +407,90 @@ private:
/// The operation that this node performs.
int16_t NodeType;
- /// This tracks whether this node has one or more dbg_value
- /// nodes corresponding to it.
- uint16_t HasDebugValue : 1;
-
protected:
- /// This member is defined by this class, but is not used for
- /// anything. Subclasses can use it to hold whatever state they find useful.
- /// This field is initialized to zero by the ctor.
- uint16_t SubclassData : 15;
+ // We define a set of mini-helper classes to help us interpret the bits in our
+ // SubclassData. These are designed to fit within a uint16_t so they pack
+ // with NodeType.
+
+ class SDNodeBitfields {
+ friend class SDNode;
+ friend class MemIntrinsicSDNode;
+ friend class MemSDNode;
+
+ uint16_t HasDebugValue : 1;
+ uint16_t IsMemIntrinsic : 1;
+ };
+ enum { NumSDNodeBits = 2 };
+
+ class ConstantSDNodeBitfields {
+ friend class ConstantSDNode;
+
+ uint16_t : NumSDNodeBits;
+
+ uint16_t IsOpaque : 1;
+ };
+
+ class MemSDNodeBitfields {
+ friend class MemSDNode;
+ friend class MemIntrinsicSDNode;
+ friend class AtomicSDNode;
+
+ uint16_t : NumSDNodeBits;
+
+ uint16_t IsVolatile : 1;
+ uint16_t IsNonTemporal : 1;
+ uint16_t IsDereferenceable : 1;
+ uint16_t IsInvariant : 1;
+ };
+ enum { NumMemSDNodeBits = NumSDNodeBits + 4 };
+
+ class LSBaseSDNodeBitfields {
+ friend class LSBaseSDNode;
+ uint16_t : NumMemSDNodeBits;
+
+ uint16_t AddressingMode : 3; // enum ISD::MemIndexedMode
+ };
+ enum { NumLSBaseSDNodeBits = NumMemSDNodeBits + 3 };
+
+ class LoadSDNodeBitfields {
+ friend class LoadSDNode;
+ friend class MaskedLoadSDNode;
+
+ uint16_t : NumLSBaseSDNodeBits;
+
+ uint16_t ExtTy : 2; // enum ISD::LoadExtType
+ uint16_t IsExpanding : 1;
+ };
+
+ class StoreSDNodeBitfields {
+ friend class StoreSDNode;
+ friend class MaskedStoreSDNode;
+
+ uint16_t : NumLSBaseSDNodeBits;
+
+ uint16_t IsTruncating : 1;
+ uint16_t IsCompressing : 1;
+ };
+
+ union {
+ char RawSDNodeBits[sizeof(uint16_t)];
+ SDNodeBitfields SDNodeBits;
+ ConstantSDNodeBitfields ConstantSDNodeBits;
+ MemSDNodeBitfields MemSDNodeBits;
+ LSBaseSDNodeBitfields LSBaseSDNodeBits;
+ LoadSDNodeBitfields LoadSDNodeBits;
+ StoreSDNodeBitfields StoreSDNodeBits;
+ };
+
+ // RawSDNodeBits must cover the entirety of the union. This means that all of
+ // the union's members must have size <= RawSDNodeBits. We write the RHS as
+ // "2" instead of sizeof(RawSDNodeBits) because MSVC can't handle the latter.
+ static_assert(sizeof(SDNodeBitfields) <= 2, "field too wide");
+ static_assert(sizeof(ConstantSDNodeBitfields) <= 2, "field too wide");
+ static_assert(sizeof(MemSDNodeBitfields) <= 2, "field too wide");
+ static_assert(sizeof(LSBaseSDNodeBitfields) <= 2, "field too wide");
+ static_assert(sizeof(LoadSDNodeBitfields) <= 4, "field too wide");
+ static_assert(sizeof(StoreSDNodeBitfields) <= 2, "field too wide");
private:
/// Unique id per SDNode in the DAG.
@@ -441,7 +523,6 @@ private:
static const EVT *getValueTypeList(EVT VT);
friend class SelectionDAG;
- friend struct ilist_traits<SDNode>;
// TODO: unfriend HandleSDNode once we fix its operand handling.
friend class HandleSDNode;
@@ -481,7 +562,8 @@ public:
/// proper classof relationship.
bool isMemIntrinsic() const {
return (NodeType == ISD::INTRINSIC_W_CHAIN ||
- NodeType == ISD::INTRINSIC_VOID) && ((SubclassData >> 13) & 1);
+ NodeType == ISD::INTRINSIC_VOID) &&
+ SDNodeBits.IsMemIntrinsic;
}
/// Test if this node has a post-isel opcode, directly
@@ -496,11 +578,8 @@ public:
return ~NodeType;
}
- /// Get this bit.
- bool getHasDebugValue() const { return HasDebugValue; }
-
- /// Set this bit.
- void setHasDebugValue(bool b) { HasDebugValue = b; }
+ bool getHasDebugValue() const { return SDNodeBits.HasDebugValue; }
+ void setHasDebugValue(bool b) { SDNodeBits.HasDebugValue = b; }
/// Return true if there are no uses of this node.
bool use_empty() const { return UseList == nullptr; }
@@ -538,9 +617,11 @@ public:
class use_iterator
: public std::iterator<std::forward_iterator_tag, SDUse, ptrdiff_t> {
SDUse *Op;
- explicit use_iterator(SDUse *op) : Op(op) {
- }
+
friend class SDNode;
+
+ explicit use_iterator(SDUse *op) : Op(op) {}
+
public:
typedef std::iterator<std::forward_iterator_tag,
SDUse, ptrdiff_t>::reference reference;
@@ -668,6 +749,7 @@ public:
}
typedef SDUse* op_iterator;
+
op_iterator op_begin() const { return OperandList; }
op_iterator op_end() const { return OperandList+NumOperands; }
ArrayRef<SDUse> ops() const { return makeArrayRef(op_begin(), op_end()); }
@@ -767,7 +849,6 @@ public:
void printrWithDepth(raw_ostream &O, const SelectionDAG *G = nullptr,
unsigned depth = 100) const;
-
/// Dump this node, for debugging.
void dump() const;
@@ -815,10 +896,10 @@ protected:
/// SDNodes are created without any operands, and never own the operand
/// storage. To add operands, see SelectionDAG::createOperands.
SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs)
- : NodeType(Opc), HasDebugValue(false), SubclassData(0), NodeId(-1),
- OperandList(nullptr), ValueList(VTs.VTs), UseList(nullptr),
- NumOperands(0), NumValues(VTs.NumVTs), IROrder(Order),
+ : NodeType(Opc), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs),
+ UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), IROrder(Order),
debugLoc(std::move(dl)) {
+ memset(&RawSDNodeBits, 0, sizeof(RawSDNodeBits));
assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
assert(NumValues == VTs.NumVTs &&
"NumValues wasn't wide enough for its operands!");
@@ -851,16 +932,19 @@ public:
if (I)
DL = I->getDebugLoc();
}
+
unsigned getIROrder() const { return IROrder; }
const DebugLoc &getDebugLoc() const { return DL; }
};
-
// Define inline functions from the SDValue class.
inline SDValue::SDValue(SDNode *node, unsigned resno)
: Node(node), ResNo(resno) {
- assert((!Node || ResNo < Node->getNumValues()) &&
+ // Explicitly check for !ResNo to avoid use-after-free, because there are
+ // callers that use SDValue(N, 0) with a deleted N to indicate successful
+ // combines.
+ assert((!Node || !ResNo || ResNo < Node->getNumValues()) &&
"Invalid result number for the given node!");
assert(ResNo < -2U && "Cannot use result numbers reserved for DenseMaps.");
}
@@ -868,48 +952,63 @@ inline SDValue::SDValue(SDNode *node, unsigned resno)
inline unsigned SDValue::getOpcode() const {
return Node->getOpcode();
}
+
inline EVT SDValue::getValueType() const {
return Node->getValueType(ResNo);
}
+
inline unsigned SDValue::getNumOperands() const {
return Node->getNumOperands();
}
+
inline const SDValue &SDValue::getOperand(unsigned i) const {
return Node->getOperand(i);
}
+
inline uint64_t SDValue::getConstantOperandVal(unsigned i) const {
return Node->getConstantOperandVal(i);
}
+
inline bool SDValue::isTargetOpcode() const {
return Node->isTargetOpcode();
}
+
inline bool SDValue::isTargetMemoryOpcode() const {
return Node->isTargetMemoryOpcode();
}
+
inline bool SDValue::isMachineOpcode() const {
return Node->isMachineOpcode();
}
+
inline unsigned SDValue::getMachineOpcode() const {
return Node->getMachineOpcode();
}
+
inline bool SDValue::isUndef() const {
return Node->isUndef();
}
+
inline bool SDValue::use_empty() const {
return !Node->hasAnyUseOfValue(ResNo);
}
+
inline bool SDValue::hasOneUse() const {
return Node->hasNUsesOfValue(1, ResNo);
}
+
inline const DebugLoc &SDValue::getDebugLoc() const {
return Node->getDebugLoc();
}
+
inline void SDValue::dump() const {
return Node->dump();
}
+
inline void SDValue::dumpr() const {
return Node->dumpr();
}
+
// Define inline functions from the SDUse class.
inline void SDUse::set(const SDValue &V) {
@@ -956,9 +1055,11 @@ static bool isBinOpWithFlags(unsigned Opcode) {
class BinaryWithFlagsSDNode : public SDNode {
public:
SDNodeFlags Flags;
+
BinaryWithFlagsSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl,
SDVTList VTs, const SDNodeFlags &NodeFlags)
: SDNode(Opc, Order, dl, VTs), Flags(NodeFlags) {}
+
static bool classof(const SDNode *N) {
return isBinOpWithFlags(N->getOpcode());
}
@@ -970,6 +1071,7 @@ public:
/// the AllNodes list.
class HandleSDNode : public SDNode {
SDUse Op;
+
public:
explicit HandleSDNode(SDValue X)
: SDNode(ISD::HANDLENODE, 0, DebugLoc(), getSDVTList(MVT::Other)) {
@@ -987,6 +1089,7 @@ public:
OperandList = &Op;
}
~HandleSDNode();
+
const SDValue &getValue() const { return Op; }
};
@@ -1032,25 +1135,27 @@ public:
return MMO->getAlignment();
}
- /// Return the SubclassData value, which contains an
+ /// Return the SubclassData value, without HasDebugValue. This contains an
/// encoding of the volatile flag, as well as bits used by subclasses. This
/// function should only be used to compute a FoldingSetNodeID value.
+ /// The HasDebugValue bit is masked out because CSE map needs to match
+ /// nodes with debug info with nodes without debug info.
unsigned getRawSubclassData() const {
- return SubclassData;
+ uint16_t Data;
+ union {
+ char RawSDNodeBits[sizeof(uint16_t)];
+ SDNodeBitfields SDNodeBits;
+ };
+ memcpy(&RawSDNodeBits, &this->RawSDNodeBits, sizeof(this->RawSDNodeBits));
+ SDNodeBits.HasDebugValue = 0;
+ memcpy(&Data, &RawSDNodeBits, sizeof(RawSDNodeBits));
+ return Data;
}
- // We access subclass data here so that we can check consistency
- // with MachineMemOperand information.
- bool isVolatile() const { return (SubclassData >> 5) & 1; }
- bool isNonTemporal() const { return (SubclassData >> 6) & 1; }
- bool isInvariant() const { return (SubclassData >> 7) & 1; }
-
- AtomicOrdering getOrdering() const {
- return AtomicOrdering((SubclassData >> 8) & 15);
- }
- SynchronizationScope getSynchScope() const {
- return SynchronizationScope((SubclassData >> 12) & 1);
- }
+ bool isVolatile() const { return MemSDNodeBits.IsVolatile; }
+ bool isNonTemporal() const { return MemSDNodeBits.IsNonTemporal; }
+ bool isDereferenceable() const { return MemSDNodeBits.IsDereferenceable; }
+ bool isInvariant() const { return MemSDNodeBits.IsInvariant; }
// Returns the offset from the location of the access.
int64_t getSrcValueOffset() const { return MMO->getOffset(); }
@@ -1061,6 +1166,14 @@ public:
/// Returns the Ranges that describes the dereference.
const MDNode *getRanges() const { return MMO->getRanges(); }
+ /// Return the synchronization scope for this memory operation.
+ SynchronizationScope getSynchScope() const { return MMO->getSynchScope(); }
+
+ /// Return the atomic ordering requirements for this memory operation. For
+ /// cmpxchg atomic operations, return the atomic ordering requirements when
+ /// store occurs.
+ AtomicOrdering getOrdering() const { return MMO->getOrdering(); }
+
/// Return the type of the in-memory value.
EVT getMemoryVT() const { return MemoryVT; }
@@ -1123,57 +1236,27 @@ public:
/// This is an SDNode representing atomic operations.
class AtomicSDNode : public MemSDNode {
- /// For cmpxchg instructions, the ordering requirements when a store does not
- /// occur.
- AtomicOrdering FailureOrdering;
-
- void InitAtomic(AtomicOrdering SuccessOrdering,
- AtomicOrdering FailureOrdering,
- SynchronizationScope SynchScope) {
- // This must match encodeMemSDNodeFlags() in SelectionDAG.cpp.
- assert((AtomicOrdering)((unsigned)SuccessOrdering & 15) ==
- SuccessOrdering &&
- "Ordering may not require more than 4 bits!");
- assert((AtomicOrdering)((unsigned)FailureOrdering & 15) ==
- FailureOrdering &&
- "Ordering may not require more than 4 bits!");
- assert((SynchScope & 1) == SynchScope &&
- "SynchScope may not require more than 1 bit!");
- SubclassData |= (unsigned)SuccessOrdering << 8;
- SubclassData |= SynchScope << 12;
- this->FailureOrdering = FailureOrdering;
- assert(getSuccessOrdering() == SuccessOrdering &&
- "Ordering encoding error!");
- assert(getFailureOrdering() == FailureOrdering &&
- "Ordering encoding error!");
- assert(getSynchScope() == SynchScope && "Synch-scope encoding error!");
- }
-
public:
AtomicSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, SDVTList VTL,
- EVT MemVT, MachineMemOperand *MMO,
- AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering,
- SynchronizationScope SynchScope)
- : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
- InitAtomic(SuccessOrdering, FailureOrdering, SynchScope);
- }
+ EVT MemVT, MachineMemOperand *MMO)
+ : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {}
const SDValue &getBasePtr() const { return getOperand(1); }
const SDValue &getVal() const { return getOperand(2); }
- AtomicOrdering getSuccessOrdering() const {
- return getOrdering();
+ /// Returns true if this SDNode represents cmpxchg atomic operation, false
+ /// otherwise.
+ bool isCompareAndSwap() const {
+ unsigned Op = getOpcode();
+ return Op == ISD::ATOMIC_CMP_SWAP ||
+ Op == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS;
}
- // Not quite enough room in SubclassData for everything, so failure gets its
- // own field.
+ /// For cmpxchg atomic operations, return the atomic ordering requirements
+ /// when store does not occur.
AtomicOrdering getFailureOrdering() const {
- return FailureOrdering;
- }
-
- bool isCompareAndSwap() const {
- unsigned Op = getOpcode();
- return Op == ISD::ATOMIC_CMP_SWAP || Op == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS;
+ assert(isCompareAndSwap() && "Must be cmpxchg operation");
+ return MMO->getFailureOrdering();
}
// Methods to support isa and dyn_cast
@@ -1205,7 +1288,7 @@ public:
MemIntrinsicSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl,
SDVTList VTs, EVT MemoryVT, MachineMemOperand *MMO)
: MemSDNode(Opc, Order, dl, VTs, MemoryVT, MMO) {
- SubclassData |= 1u << 13;
+ SDNodeBits.IsMemIntrinsic = true;
}
// Methods to support isa and dyn_cast
@@ -1230,8 +1313,10 @@ class ShuffleVectorSDNode : public SDNode {
// The memory for Mask is owned by the SelectionDAG's OperandAllocator, and
// is freed when the SelectionDAG object is destroyed.
const int *Mask;
+
protected:
friend class SelectionDAG;
+
ShuffleVectorSDNode(EVT VT, unsigned Order, const DebugLoc &dl, const int *M)
: SDNode(ISD::VECTOR_SHUFFLE, Order, dl, getSDVTList(VT)), Mask(M) {}
@@ -1240,12 +1325,14 @@ public:
EVT VT = getValueType(0);
return makeArrayRef(Mask, VT.getVectorNumElements());
}
+
int getMaskElt(unsigned Idx) const {
assert(Idx < getValueType(0).getVectorNumElements() && "Idx out of range!");
return Mask[Idx];
}
bool isSplat() const { return isSplatMask(Mask, getValueType(0)); }
+
int getSplatIndex() const {
assert(isSplat() && "Cannot get splat index for non-splat!");
EVT VT = getValueType(0);
@@ -1255,6 +1342,7 @@ public:
}
llvm_unreachable("Splat with all undef indices?");
}
+
static bool isSplatMask(const int *Mask, EVT VT);
/// Change values in a shuffle permute mask assuming
@@ -1279,16 +1367,18 @@ public:
class ConstantSDNode : public SDNode {
const ConstantInt *Value;
+
friend class SelectionDAG;
+
ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val,
const DebugLoc &DL, EVT VT)
: SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, 0, DL,
getSDVTList(VT)),
Value(val) {
- SubclassData |= (uint16_t)isOpaque;
+ ConstantSDNodeBits.IsOpaque = isOpaque;
}
-public:
+public:
const ConstantInt *getConstantIntValue() const { return Value; }
const APInt &getAPIntValue() const { return Value->getValue(); }
uint64_t getZExtValue() const { return Value->getZExtValue(); }
@@ -1298,7 +1388,7 @@ public:
bool isNullValue() const { return Value->isNullValue(); }
bool isAllOnesValue() const { return Value->isAllOnesValue(); }
- bool isOpaque() const { return SubclassData & 1; }
+ bool isOpaque() const { return ConstantSDNodeBits.IsOpaque; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::Constant ||
@@ -1308,7 +1398,9 @@ public:
class ConstantFPSDNode : public SDNode {
const ConstantFP *Value;
+
friend class SelectionDAG;
+
ConstantFPSDNode(bool isTarget, const ConstantFP *val, const DebugLoc &DL,
EVT VT)
: SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, 0, DL,
@@ -1316,7 +1408,6 @@ class ConstantFPSDNode : public SDNode {
Value(val) {}
public:
-
const APFloat& getValueAPF() const { return Value->getValueAPF(); }
const ConstantFP *getConstantFPValue() const { return Value; }
@@ -1359,16 +1450,26 @@ public:
/// Returns true if \p V is a constant integer zero.
bool isNullConstant(SDValue V);
+
/// Returns true if \p V is an FP constant with a value of positive zero.
bool isNullFPConstant(SDValue V);
+
/// Returns true if \p V is an integer constant with all bits set.
bool isAllOnesConstant(SDValue V);
+
/// Returns true if \p V is a constant integer one.
bool isOneConstant(SDValue V);
+
/// Returns true if \p V is a bitwise not operation. Assumes that an all ones
/// constant is canonicalized to be operand 1.
bool isBitwiseNot(SDValue V);
+/// Returns the SDNode if it is a constant splat BuildVector or constant int.
+ConstantSDNode *isConstOrConstSplat(SDValue V);
+
+/// Returns the SDNode if it is a constant splat BuildVector or constant float.
+ConstantFPSDNode *isConstOrConstSplatFP(SDValue V);
+
class GlobalAddressSDNode : public SDNode {
const GlobalValue *TheGlobal;
int64_t Offset;
@@ -1379,7 +1480,6 @@ class GlobalAddressSDNode : public SDNode {
unsigned char TargetFlags);
public:
-
const GlobalValue *getGlobal() const { return TheGlobal; }
int64_t getOffset() const { return Offset; }
unsigned char getTargetFlags() const { return TargetFlags; }
@@ -1396,13 +1496,15 @@ public:
class FrameIndexSDNode : public SDNode {
int FI;
+
friend class SelectionDAG;
+
FrameIndexSDNode(int fi, EVT VT, bool isTarg)
: SDNode(isTarg ? ISD::TargetFrameIndex : ISD::FrameIndex,
0, DebugLoc(), getSDVTList(VT)), FI(fi) {
}
-public:
+public:
int getIndex() const { return FI; }
static bool classof(const SDNode *N) {
@@ -1414,13 +1516,15 @@ public:
class JumpTableSDNode : public SDNode {
int JTI;
unsigned char TargetFlags;
+
friend class SelectionDAG;
+
JumpTableSDNode(int jti, EVT VT, bool isTarg, unsigned char TF)
: SDNode(isTarg ? ISD::TargetJumpTable : ISD::JumpTable,
0, DebugLoc(), getSDVTList(VT)), JTI(jti), TargetFlags(TF) {
}
-public:
+public:
int getIndex() const { return JTI; }
unsigned char getTargetFlags() const { return TargetFlags; }
@@ -1438,7 +1542,9 @@ class ConstantPoolSDNode : public SDNode {
int Offset; // It's a MachineConstantPoolValue if top bit is set.
unsigned Alignment; // Minimum alignment requirement of CP (not log2 value).
unsigned char TargetFlags;
+
friend class SelectionDAG;
+
ConstantPoolSDNode(bool isTarget, const Constant *c, EVT VT, int o,
unsigned Align, unsigned char TF)
: SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, 0,
@@ -1447,6 +1553,7 @@ class ConstantPoolSDNode : public SDNode {
assert(Offset >= 0 && "Offset is too large");
Val.ConstVal = c;
}
+
ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v,
EVT VT, int o, unsigned Align, unsigned char TF)
: SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, 0,
@@ -1456,8 +1563,8 @@ class ConstantPoolSDNode : public SDNode {
Val.MachineCPVal = v;
Offset |= 1 << (sizeof(unsigned)*CHAR_BIT-1);
}
-public:
+public:
bool isMachineConstantPoolEntry() const {
return Offset < 0;
}
@@ -1494,13 +1601,13 @@ class TargetIndexSDNode : public SDNode {
unsigned char TargetFlags;
int Index;
int64_t Offset;
+
friend class SelectionDAG;
-public:
+public:
TargetIndexSDNode(int Idx, EVT VT, int64_t Ofs, unsigned char TF)
: SDNode(ISD::TargetIndex, 0, DebugLoc(), getSDVTList(VT)),
TargetFlags(TF), Index(Idx), Offset(Ofs) {}
-public:
unsigned char getTargetFlags() const { return TargetFlags; }
int getIndex() const { return Index; }
@@ -1513,15 +1620,17 @@ public:
class BasicBlockSDNode : public SDNode {
MachineBasicBlock *MBB;
+
friend class SelectionDAG;
+
/// Debug info is meaningful and potentially useful here, but we create
/// blocks out of order when they're jumped to, which makes it a bit
/// harder. Let's see if we need it first.
explicit BasicBlockSDNode(MachineBasicBlock *mbb)
: SDNode(ISD::BasicBlock, 0, DebugLoc(), getSDVTList(MVT::Other)), MBB(mbb)
{}
-public:
+public:
MachineBasicBlock *getBasicBlock() const { return MBB; }
static bool classof(const SDNode *N) {
@@ -1533,6 +1642,7 @@ public:
class BuildVectorSDNode : public SDNode {
// These are constructed as SDNodes and then cast to BuildVectorSDNodes.
explicit BuildVectorSDNode() = delete;
+
public:
/// Check if this is a constant splat, and if so, find the
/// smallest element size that splats the vector. If MinSplatBits is
@@ -1591,7 +1701,9 @@ public:
///
class SrcValueSDNode : public SDNode {
const Value *V;
+
friend class SelectionDAG;
+
/// Create a SrcValue for a general value.
explicit SrcValueSDNode(const Value *v)
: SDNode(ISD::SRCVALUE, 0, DebugLoc(), getSDVTList(MVT::Other)), V(v) {}
@@ -1607,12 +1719,14 @@ public:
class MDNodeSDNode : public SDNode {
const MDNode *MD;
+
friend class SelectionDAG;
+
explicit MDNodeSDNode(const MDNode *md)
: SDNode(ISD::MDNODE_SDNODE, 0, DebugLoc(), getSDVTList(MVT::Other)), MD(md)
{}
-public:
+public:
const MDNode *getMD() const { return MD; }
static bool classof(const SDNode *N) {
@@ -1622,12 +1736,13 @@ public:
class RegisterSDNode : public SDNode {
unsigned Reg;
+
friend class SelectionDAG;
+
RegisterSDNode(unsigned reg, EVT VT)
- : SDNode(ISD::Register, 0, DebugLoc(), getSDVTList(VT)), Reg(reg) {
- }
-public:
+ : SDNode(ISD::Register, 0, DebugLoc(), getSDVTList(VT)), Reg(reg) {}
+public:
unsigned getReg() const { return Reg; }
static bool classof(const SDNode *N) {
@@ -1638,12 +1753,14 @@ public:
class RegisterMaskSDNode : public SDNode {
// The memory for RegMask is not owned by the node.
const uint32_t *RegMask;
+
friend class SelectionDAG;
+
RegisterMaskSDNode(const uint32_t *mask)
: SDNode(ISD::RegisterMask, 0, DebugLoc(), getSDVTList(MVT::Untyped)),
RegMask(mask) {}
-public:
+public:
const uint32_t *getRegMask() const { return RegMask; }
static bool classof(const SDNode *N) {
@@ -1655,12 +1772,15 @@ class BlockAddressSDNode : public SDNode {
const BlockAddress *BA;
int64_t Offset;
unsigned char TargetFlags;
+
friend class SelectionDAG;
+
BlockAddressSDNode(unsigned NodeTy, EVT VT, const BlockAddress *ba,
int64_t o, unsigned char Flags)
: SDNode(NodeTy, 0, DebugLoc(), getSDVTList(VT)),
BA(ba), Offset(o), TargetFlags(Flags) {
}
+
public:
const BlockAddress *getBlockAddress() const { return BA; }
int64_t getOffset() const { return Offset; }
@@ -1674,7 +1794,9 @@ public:
class EHLabelSDNode : public SDNode {
MCSymbol *Label;
+
friend class SelectionDAG;
+
EHLabelSDNode(unsigned Order, const DebugLoc &dl, MCSymbol *L)
: SDNode(ISD::EH_LABEL, Order, dl, getSDVTList(MVT::Other)), Label(L) {}
@@ -1691,12 +1813,12 @@ class ExternalSymbolSDNode : public SDNode {
unsigned char TargetFlags;
friend class SelectionDAG;
+
ExternalSymbolSDNode(bool isTarget, const char *Sym, unsigned char TF, EVT VT)
: SDNode(isTarget ? ISD::TargetExternalSymbol : ISD::ExternalSymbol,
- 0, DebugLoc(), getSDVTList(VT)), Symbol(Sym), TargetFlags(TF) {
- }
-public:
+ 0, DebugLoc(), getSDVTList(VT)), Symbol(Sym), TargetFlags(TF) {}
+public:
const char *getSymbol() const { return Symbol; }
unsigned char getTargetFlags() const { return TargetFlags; }
@@ -1723,13 +1845,14 @@ public:
class CondCodeSDNode : public SDNode {
ISD::CondCode Condition;
+
friend class SelectionDAG;
+
explicit CondCodeSDNode(ISD::CondCode Cond)
: SDNode(ISD::CONDCODE, 0, DebugLoc(), getSDVTList(MVT::Other)),
- Condition(Cond) {
- }
-public:
+ Condition(Cond) {}
+public:
ISD::CondCode get() const { return Condition; }
static bool classof(const SDNode *N) {
@@ -1741,7 +1864,9 @@ public:
/// future and most targets don't support it.
class CvtRndSatSDNode : public SDNode {
ISD::CvtCode CvtCode;
+
friend class SelectionDAG;
+
explicit CvtRndSatSDNode(EVT VT, unsigned Order, const DebugLoc &dl,
ISD::CvtCode Code)
: SDNode(ISD::CONVERT_RNDSAT, Order, dl, getSDVTList(VT)), CvtCode(Code) {
@@ -1759,13 +1884,14 @@ public:
/// to parameterize some operations.
class VTSDNode : public SDNode {
EVT ValueType;
+
friend class SelectionDAG;
+
explicit VTSDNode(EVT VT)
: SDNode(ISD::VALUETYPE, 0, DebugLoc(), getSDVTList(MVT::Other)),
- ValueType(VT) {
- }
-public:
+ ValueType(VT) {}
+public:
EVT getVT() const { return ValueType; }
static bool classof(const SDNode *N) {
@@ -1780,8 +1906,8 @@ public:
SDVTList VTs, ISD::MemIndexedMode AM, EVT MemVT,
MachineMemOperand *MMO)
: MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {
- SubclassData |= AM << 2;
- assert(getAddressingMode() == AM && "MemIndexedMode encoding error!");
+ LSBaseSDNodeBits.AddressingMode = AM;
+ assert(getAddressingMode() == AM && "Value truncated");
}
const SDValue &getOffset() const {
@@ -1791,7 +1917,7 @@ public:
/// Return the addressing mode for this load or store:
/// unindexed, pre-inc, pre-dec, post-inc, or post-dec.
ISD::MemIndexedMode getAddressingMode() const {
- return ISD::MemIndexedMode((SubclassData >> 2) & 7);
+ return static_cast<ISD::MemIndexedMode>(LSBaseSDNodeBits.AddressingMode);
}
/// Return true if this is a pre/post inc/dec load/store.
@@ -1809,21 +1935,21 @@ public:
/// This class is used to represent ISD::LOAD nodes.
class LoadSDNode : public LSBaseSDNode {
friend class SelectionDAG;
+
LoadSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
ISD::MemIndexedMode AM, ISD::LoadExtType ETy, EVT MemVT,
MachineMemOperand *MMO)
: LSBaseSDNode(ISD::LOAD, Order, dl, VTs, AM, MemVT, MMO) {
- SubclassData |= (unsigned short)ETy;
- assert(getExtensionType() == ETy && "LoadExtType encoding error!");
+ LoadSDNodeBits.ExtTy = ETy;
assert(readMem() && "Load MachineMemOperand is not a load!");
assert(!writeMem() && "Load MachineMemOperand is a store!");
}
-public:
+public:
/// Return whether this is a plain node,
/// or one of the varieties of value-extending loads.
ISD::LoadExtType getExtensionType() const {
- return ISD::LoadExtType(SubclassData & 3);
+ return static_cast<ISD::LoadExtType>(LoadSDNodeBits.ExtTy);
}
const SDValue &getBasePtr() const { return getOperand(1); }
@@ -1837,21 +1963,21 @@ public:
/// This class is used to represent ISD::STORE nodes.
class StoreSDNode : public LSBaseSDNode {
friend class SelectionDAG;
+
StoreSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT,
MachineMemOperand *MMO)
: LSBaseSDNode(ISD::STORE, Order, dl, VTs, AM, MemVT, MMO) {
- SubclassData |= (unsigned short)isTrunc;
- assert(isTruncatingStore() == isTrunc && "isTrunc encoding error!");
+ StoreSDNodeBits.IsTruncating = isTrunc;
assert(!readMem() && "Store MachineMemOperand is a load!");
assert(writeMem() && "Store MachineMemOperand is not a store!");
}
-public:
+public:
/// Return true if the op does a truncation before store.
/// For integers this is the same as doing a TRUNCATE and storing the result.
/// For floats, it is the same as doing an FP_ROUND and storing the result.
- bool isTruncatingStore() const { return SubclassData & 1; }
+ bool isTruncatingStore() const { return StoreSDNodeBits.IsTruncating; }
const SDValue &getValue() const { return getOperand(1); }
const SDValue &getBasePtr() const { return getOperand(2); }
@@ -1866,6 +1992,7 @@ public:
class MaskedLoadStoreSDNode : public MemSDNode {
public:
friend class SelectionDAG;
+
MaskedLoadStoreSDNode(ISD::NodeType NodeTy, unsigned Order,
const DebugLoc &dl, SDVTList VTs, EVT MemVT,
MachineMemOperand *MMO)
@@ -1889,34 +2016,48 @@ class MaskedLoadSDNode : public MaskedLoadStoreSDNode {
public:
friend class SelectionDAG;
MaskedLoadSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
- ISD::LoadExtType ETy, EVT MemVT, MachineMemOperand *MMO)
+ ISD::LoadExtType ETy, bool IsExpanding, EVT MemVT,
+ MachineMemOperand *MMO)
: MaskedLoadStoreSDNode(ISD::MLOAD, Order, dl, VTs, MemVT, MMO) {
- SubclassData |= (unsigned short)ETy;
+ LoadSDNodeBits.ExtTy = ETy;
+ LoadSDNodeBits.IsExpanding = IsExpanding;
}
ISD::LoadExtType getExtensionType() const {
- return ISD::LoadExtType(SubclassData & 3);
+ return static_cast<ISD::LoadExtType>(LoadSDNodeBits.ExtTy);
}
+
const SDValue &getSrc0() const { return getOperand(3); }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::MLOAD;
}
+
+ bool isExpandingLoad() const { return LoadSDNodeBits.IsExpanding; }
};
/// This class is used to represent an MSTORE node
class MaskedStoreSDNode : public MaskedLoadStoreSDNode {
-
public:
friend class SelectionDAG;
+
MaskedStoreSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
- bool isTrunc, EVT MemVT, MachineMemOperand *MMO)
+ bool isTrunc, bool isCompressing, EVT MemVT,
+ MachineMemOperand *MMO)
: MaskedLoadStoreSDNode(ISD::MSTORE, Order, dl, VTs, MemVT, MMO) {
- SubclassData |= (unsigned short)isTrunc;
+ StoreSDNodeBits.IsTruncating = isTrunc;
+ StoreSDNodeBits.IsCompressing = isCompressing;
}
+
/// Return true if the op does a truncation before store.
/// For integers this is the same as doing a TRUNCATE and storing the result.
/// For floats, it is the same as doing an FP_ROUND and storing the result.
- bool isTruncatingStore() const { return SubclassData & 1; }
+ bool isTruncatingStore() const { return StoreSDNodeBits.IsTruncating; }
+
+ /// Returns true if the op does a compression to the vector before storing.
+ /// The node contiguously stores the active elements (integers or floats)
+ /// in src (those with their respective bit set in writemask k) to unaligned
+ /// memory at base_addr.
+ bool isCompressingStore() const { return StoreSDNodeBits.IsCompressing; }
const SDValue &getValue() const { return getOperand(3); }
@@ -1931,6 +2072,7 @@ public:
class MaskedGatherScatterSDNode : public MemSDNode {
public:
friend class SelectionDAG;
+
MaskedGatherScatterSDNode(ISD::NodeType NodeTy, unsigned Order,
const DebugLoc &dl, SDVTList VTs, EVT MemVT,
MachineMemOperand *MMO)
@@ -1956,6 +2098,7 @@ public:
class MaskedGatherSDNode : public MaskedGatherScatterSDNode {
public:
friend class SelectionDAG;
+
MaskedGatherSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
EVT MemVT, MachineMemOperand *MMO)
: MaskedGatherScatterSDNode(ISD::MGATHER, Order, dl, VTs, MemVT, MMO) {}
@@ -1968,9 +2111,9 @@ public:
/// This class is used to represent an MSCATTER node
///
class MaskedScatterSDNode : public MaskedGatherScatterSDNode {
-
public:
friend class SelectionDAG;
+
MaskedScatterSDNode(unsigned Order, const DebugLoc &dl, SDVTList VTs,
EVT MemVT, MachineMemOperand *MMO)
: MaskedGatherScatterSDNode(ISD::MSCATTER, Order, dl, VTs, MemVT, MMO) {}
@@ -1989,6 +2132,7 @@ public:
private:
friend class SelectionDAG;
+
MachineSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL, SDVTList VTs)
: SDNode(Opc, Order, DL, VTs), MemRefs(nullptr), MemRefsEnd(nullptr) {}
@@ -2021,6 +2165,7 @@ class SDNodeIterator : public std::iterator<std::forward_iterator_tag,
unsigned Operand;
SDNodeIterator(const SDNode *N, unsigned Op) : Node(N), Operand(Op) {}
+
public:
bool operator==(const SDNodeIterator& x) const {
return Operand == x.Operand;
@@ -2055,13 +2200,14 @@ public:
};
template <> struct GraphTraits<SDNode*> {
- typedef SDNode NodeType;
+ typedef SDNode *NodeRef;
typedef SDNodeIterator ChildIteratorType;
- static inline NodeType *getEntryNode(SDNode *N) { return N; }
- static inline ChildIteratorType child_begin(NodeType *N) {
+
+ static NodeRef getEntryNode(SDNode *N) { return N; }
+ static ChildIteratorType child_begin(NodeRef N) {
return SDNodeIterator::begin(N);
}
- static inline ChildIteratorType child_end(NodeType *N) {
+ static ChildIteratorType child_end(NodeRef N) {
return SDNodeIterator::end(N);
}
};
@@ -2078,6 +2224,7 @@ typedef AlignedCharArrayUnion<AtomicSDNode, TargetIndexSDNode,
typedef GlobalAddressSDNode MostAlignedSDNode;
namespace ISD {
+
/// Returns true if the specified node is a non-extending and unindexed load.
inline bool isNormalLoad(const SDNode *N) {
const LoadSDNode *Ld = dyn_cast<LoadSDNode>(N);
@@ -2138,8 +2285,9 @@ namespace ISD {
return isa<StoreSDNode>(N) &&
cast<StoreSDNode>(N)->getAddressingMode() == ISD::UNINDEXED;
}
-}
-} // end llvm namespace
+} // end namespace ISD
+
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_SELECTIONDAGNODES_H