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