#ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H
#define LLVM_CODEGEN_SELECTIONDAGNODES_H
-#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Value.h"
+#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/iterator"
-#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Support/DataTypes.h"
#include <cassert>
class SelectionDAG;
class GlobalValue;
class MachineBasicBlock;
+class MachineConstantPoolValue;
class SDNode;
template <typename T> struct simplify_type;
template <typename T> struct ilist_traits;
Constant, ConstantFP,
GlobalAddress, FrameIndex, JumpTable, ConstantPool, ExternalSymbol,
+ // The address of the GOT
+ GLOBAL_OFFSET_TABLE,
+
+ // FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and
+ // llvm.returnaddress on the DAG. These nodes take one operand, the index
+ // of the frame or return address to return. An index of zero corresponds
+ // to the current function's frame or return address, an index of one to the
+ // parent's frame or return address, and so on.
+ FRAMEADDR, RETURNADDR,
+
// TargetConstant* - Like Constant*, but the DAG does not do any folding or
// simplification of the constant.
TargetConstant,
// UNDEF - An undefined node
UNDEF,
- /// FORMAL_ARGUMENTS(CHAIN, CC#, ISVARARG) - This node represents the formal
- /// arguments for a function. CC# is a Constant value indicating the
- /// calling convention of the function, and ISVARARG is a flag that
- /// indicates whether the function is varargs or not. This node has one
- /// result value for each incoming argument, plus one for the output chain.
- /// It must be custom legalized.
+ /// FORMAL_ARGUMENTS(CHAIN, CC#, ISVARARG, FLAG0, ..., FLAGn) - This node
+ /// represents the formal arguments for a function. CC# is a Constant value
+ /// indicating the calling convention of the function, and ISVARARG is a
+ /// flag that indicates whether the function is varargs or not. This node
+ /// has one result value for each incoming argument, plus one for the output
+ /// chain. It must be custom legalized. See description of CALL node for
+ /// FLAG argument contents explanation.
///
FORMAL_ARGUMENTS,
/// RV1, RV2...RVn, CHAIN = CALL(CHAIN, CC#, ISVARARG, ISTAILCALL, CALLEE,
- /// ARG0, SIGN0, ARG1, SIGN1, ... ARGn, SIGNn)
+ /// ARG0, FLAG0, ARG1, FLAG1, ... ARGn, FLAGn)
/// This node represents a fully general function call, before the legalizer
- /// runs. This has one result value for each argument / signness pair, plus
- /// a chain result. It must be custom legalized.
+ /// runs. This has one result value for each argument / flag pair, plus
+ /// a chain result. It must be custom legalized. Flag argument indicates
+ /// misc. argument attributes. Currently:
+ /// Bit 0 - signness
+ /// Bit 1 - 'inreg' attribute
+ /// Bit 2 - 'sret' attribute
CALL,
// EXTRACT_ELEMENT - This is used to get the first or second (determined by
// conversions, but that is a noop, deleted by getNode().
BIT_CONVERT,
- // FNEG, FABS, FSQRT, FSIN, FCOS - Perform unary floating point negation,
- // absolute value, square root, sine and cosine operations.
- FNEG, FABS, FSQRT, FSIN, FCOS,
+ // FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI - Perform unary floating point
+ // negation, absolute value, square root, sine and cosine, and powi
+ // operations.
+ FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI,
- // Other operators. LOAD and STORE have token chains as their first
- // operand, then the same operands as an LLVM load/store instruction, then a
- // SRCVALUE node that provides alias analysis information.
+ // LOAD and STORE have token chains as their first operand, then the same
+ // operands as an LLVM load/store instruction, then an offset node that
+ // is added / subtracted from the base pointer to form the address (for
+ // indexed memory ops).
LOAD, STORE,
// Abstract vector version of LOAD. VLOAD has a constant element count as
// the elements, a token chain, a pointer operand, and a SRCVALUE node.
VLOAD,
- // EXTLOAD, SEXTLOAD, ZEXTLOAD - These three operators all load a value from
- // memory and extend them to a larger value (e.g. load a byte into a word
- // register). All three of these have four operands, a token chain, a
- // pointer to load from, a SRCVALUE for alias analysis, and a VALUETYPE node
- // indicating the type to load.
- //
- // SEXTLOAD loads the integer operand and sign extends it to a larger
- // integer result type.
- // ZEXTLOAD loads the integer operand and zero extends it to a larger
- // integer result type.
- // EXTLOAD is used for three things: floating point extending loads,
- // integer extending loads [the top bits are undefined], and vector
- // extending loads [load into low elt].
- EXTLOAD, SEXTLOAD, ZEXTLOAD,
-
// TRUNCSTORE - This operators truncates (for integer) or rounds (for FP) a
// value and stores it to memory in one operation. This can be used for
// either integer or floating point operands. The first four operands of
// is the value to branch to, which must be of the same type as the target's
// pointer type.
BRIND,
+
+ // BR_JT - Jumptable branch. The first operand is the chain, the second
+ // is the jumptable index, the last one is the jumptable entry index.
+ BR_JT,
// BRCOND - Conditional branch. The first operand is the chain,
// the second is the condition, the third is the block to branch
// Operand #2n+3: A TargetConstant, indicating if the reg is a use/def
// Operand #last: Optional, an incoming flag.
INLINEASM,
+
+ // LABEL - Represents a label in mid basic block used to track
+ // locations needed for debug and exception handling tables. This node
+ // returns a chain.
+ // Operand #0 : input chain.
+ // Operand #1 : module unique number use to identify the label.
+ LABEL,
// STACKSAVE - STACKSAVE has one operand, an input chain. It produces a
// value, the same type as the pointer type for the system, and an output
// DEBUG_LOC - This node is used to represent source line information
// embedded in the code. It takes a token chain as input, then a line
- // number, then a column then a file id (provided by MachineDebugInfo.) It
+ // number, then a column then a file id (provided by MachineModuleInfo.) It
// produces a token chain as output.
DEBUG_LOC,
- // DEBUG_LABEL - This node is used to mark a location in the code where a
- // label should be generated for use by the debug information. It takes a
- // token chain as input and then a unique id (provided by MachineDebugInfo.)
- // It produces a token chain as output.
- DEBUG_LABEL,
-
// BUILTIN_OP_END - This must be the last enum value in this list.
BUILTIN_OP_END
};
/// BUILD_VECTOR where all of the elements are 0 or undef.
bool isBuildVectorAllZeros(const SDNode *N);
+ //===--------------------------------------------------------------------===//
+ /// MemIndexedMode enum - This enum defines the load / store indexed
+ /// addressing modes.
+ ///
+ /// UNINDEXED "Normal" load / store. The effective address is already
+ /// computed and is available in the base pointer. The offset
+ /// operand is always undefined. In addition to producing a
+ /// chain, an unindexed load produces one value (result of the
+ /// load); an unindexed store does not produces a value.
+ ///
+ /// PRE_INC Similar to the unindexed mode where the effective address is
+ /// PRE_DEC the value of the base pointer add / subtract the offset.
+ /// It considers the computation as being folded into the load /
+ /// store operation (i.e. the load / store does the address
+ /// computation as well as performing the memory transaction).
+ /// The base operand is always undefined. In addition to
+ /// producing a chain, pre-indexed load produces two values
+ /// (result of the load and the result of the address
+ /// computation); a pre-indexed store produces one value (result
+ /// of the address computation).
+ ///
+ /// POST_INC The effective address is the value of the base pointer. The
+ /// POST_DEC value of the offset operand is then added to / subtracted
+ /// from the base after memory transaction. In addition to
+ /// producing a chain, post-indexed load produces two values
+ /// (the result of the load and the result of the base +/- offset
+ /// computation); a post-indexed store produces one value (the
+ /// the result of the base +/- offset computation).
+ ///
+ enum MemIndexedMode {
+ UNINDEXED = 0,
+ PRE_INC,
+ PRE_DEC,
+ POST_INC,
+ POST_DEC,
+ LAST_INDEXED_MODE
+ };
+
+ //===--------------------------------------------------------------------===//
+ /// LoadExtType enum - This enum defines the three variants of LOADEXT
+ /// (load with extension).
+ ///
+ /// SEXTLOAD loads the integer operand and sign extends it to a larger
+ /// integer result type.
+ /// ZEXTLOAD loads the integer operand and zero extends it to a larger
+ /// integer result type.
+ /// EXTLOAD is used for three things: floating point extending loads,
+ /// integer extending loads [the top bits are undefined], and vector
+ /// extending loads [load into low elt].
+ ///
+ enum LoadExtType {
+ NON_EXTLOAD = 0,
+ EXTLOAD,
+ SEXTLOAD,
+ ZEXTLOAD,
+ LAST_LOADX_TYPE
+ };
+
//===--------------------------------------------------------------------===//
/// ISD::CondCode enum - These are ordered carefully to make the bitfields
/// below work out, when considering SETFALSE (something that never exists
inline unsigned getOpcode() const;
inline unsigned getNumOperands() const;
inline const SDOperand &getOperand(unsigned i) const;
+ inline uint64_t getConstantOperandVal(unsigned i) const;
inline bool isTargetOpcode() const;
inline unsigned getTargetOpcode() const;
/// SDNode - Represents one node in the SelectionDAG.
///
-class SDNode {
+class SDNode : public FoldingSetNode {
/// NodeType - The operation that this node performs.
///
unsigned short NodeType;
SDNode *Prev, *Next;
friend struct ilist_traits<SDNode>;
- /// NextInBucket - This is used by the SelectionDAGCSEMap.
- void *NextInBucket;
-
/// Uses - These are all of the SDNode's that use a value produced by this
/// node.
SmallVector<SDNode*,3> Uses;
public:
virtual ~SDNode() {
assert(NumOperands == 0 && "Operand list not cleared before deletion");
- assert(NextInBucket == 0 && "Still in CSEMap?");
NodeType = ISD::DELETED_NODE;
}
/// operation.
bool hasNUsesOfValue(unsigned NUses, unsigned Value) const;
- // isOnlyUse - Return true if this node is the only use of N.
+ /// isOnlyUse - Return true if this node is the only use of N.
+ ///
bool isOnlyUse(SDNode *N) const;
- // isOperand - Return true if this node is an operand of N.
+ /// isOperand - Return true if this node is an operand of N.
+ ///
bool isOperand(SDNode *N) const;
+ /// isPredecessor - Return true if this node is a predecessor of N. This node
+ /// is either an operand of N or it can be reached by recursively traversing
+ /// up the operands.
+ /// NOTE: this is an expensive method. Use it carefully.
+ bool isPredecessor(SDNode *N) const;
+
/// getNumOperands - Return the number of values used by this operation.
///
unsigned getNumOperands() const { return NumOperands; }
+ /// getConstantOperandVal - Helper method returns the integer value of a
+ /// ConstantSDNode operand.
+ uint64_t getConstantOperandVal(unsigned Num) const;
+
const SDOperand &getOperand(unsigned Num) const {
assert(Num < NumOperands && "Invalid child # of SDNode!");
return OperandList[Num];
}
+
typedef const SDOperand* op_iterator;
op_iterator op_begin() const { return OperandList; }
op_iterator op_end() const { return OperandList+NumOperands; }
/// getOperationName - Return the opcode of this operation for printing.
///
const char* getOperationName(const SelectionDAG *G = 0) const;
+ static const char* getIndexedModeName(ISD::MemIndexedMode AM);
void dump() const;
void dump(const SelectionDAG *G) const;
static bool classof(const SDNode *) { return true; }
-
- /// NextInBucket accessors, these are private to SelectionDAGCSEMap.
- void *getNextInBucket() const { return NextInBucket; }
- void SetNextInBucket(void *N) { NextInBucket = N; }
-
+ /// Profile - Gather unique data for the node.
+ ///
+ void Profile(FoldingSetNodeID &ID);
+
protected:
friend class SelectionDAG;
ValueList = getValueTypeList(VT);
NumValues = 1;
Prev = 0; Next = 0;
- NextInBucket = 0;
}
SDNode(unsigned NT, SDOperand Op)
: NodeType(NT), NodeId(-1) {
ValueList = 0;
NumValues = 0;
Prev = 0; Next = 0;
- NextInBucket = 0;
}
SDNode(unsigned NT, SDOperand N1, SDOperand N2)
: NodeType(NT), NodeId(-1) {
ValueList = 0;
NumValues = 0;
Prev = 0; Next = 0;
- NextInBucket = 0;
}
SDNode(unsigned NT, SDOperand N1, SDOperand N2, SDOperand N3)
: NodeType(NT), NodeId(-1) {
ValueList = 0;
NumValues = 0;
Prev = 0; Next = 0;
- NextInBucket = 0;
}
SDNode(unsigned NT, SDOperand N1, SDOperand N2, SDOperand N3, SDOperand N4)
: NodeType(NT), NodeId(-1) {
ValueList = 0;
NumValues = 0;
Prev = 0; Next = 0;
- NextInBucket = 0;
}
SDNode(unsigned Opc, const SDOperand *Ops, unsigned NumOps)
: NodeType(Opc), NodeId(-1) {
ValueList = 0;
NumValues = 0;
Prev = 0; Next = 0;
- NextInBucket = 0;
}
/// MorphNodeTo - This clears the return value and operands list, and sets the
Op0.Val->Uses.push_back(this); Op1.Val->Uses.push_back(this);
Op2.Val->Uses.push_back(this);
}
- void setOperands(SDOperand Op0, SDOperand Op1, SDOperand Op2, SDOperand Op3) {
+ void setOperands(const SDOperand *Ops, unsigned NumOps) {
assert(NumOperands == 0 && "Should not have operands yet!");
- OperandList = new SDOperand[4];
- OperandList[0] = Op0;
- OperandList[1] = Op1;
- OperandList[2] = Op2;
- OperandList[3] = Op3;
- NumOperands = 4;
- Op0.Val->Uses.push_back(this); Op1.Val->Uses.push_back(this);
- Op2.Val->Uses.push_back(this); Op3.Val->Uses.push_back(this);
- }
- void setOperands(SDOperand Op0, SDOperand Op1, SDOperand Op2, SDOperand Op3,
- SDOperand Op4) {
- assert(NumOperands == 0 && "Should not have operands yet!");
- OperandList = new SDOperand[5];
- OperandList[0] = Op0;
- OperandList[1] = Op1;
- OperandList[2] = Op2;
- OperandList[3] = Op3;
- OperandList[4] = Op4;
- NumOperands = 5;
- Op0.Val->Uses.push_back(this); Op1.Val->Uses.push_back(this);
- Op2.Val->Uses.push_back(this); Op3.Val->Uses.push_back(this);
- Op4.Val->Uses.push_back(this);
- }
- void setOperands(SDOperand Op0, SDOperand Op1, SDOperand Op2, SDOperand Op3,
- SDOperand Op4, SDOperand Op5) {
- assert(NumOperands == 0 && "Should not have operands yet!");
- OperandList = new SDOperand[6];
- OperandList[0] = Op0;
- OperandList[1] = Op1;
- OperandList[2] = Op2;
- OperandList[3] = Op3;
- OperandList[4] = Op4;
- OperandList[5] = Op5;
- NumOperands = 6;
- Op0.Val->Uses.push_back(this); Op1.Val->Uses.push_back(this);
- Op2.Val->Uses.push_back(this); Op3.Val->Uses.push_back(this);
- Op4.Val->Uses.push_back(this); Op5.Val->Uses.push_back(this);
- }
- void setOperands(SDOperand Op0, SDOperand Op1, SDOperand Op2, SDOperand Op3,
- SDOperand Op4, SDOperand Op5, SDOperand Op6) {
- assert(NumOperands == 0 && "Should not have operands yet!");
- OperandList = new SDOperand[7];
- OperandList[0] = Op0;
- OperandList[1] = Op1;
- OperandList[2] = Op2;
- OperandList[3] = Op3;
- OperandList[4] = Op4;
- OperandList[5] = Op5;
- OperandList[6] = Op6;
- NumOperands = 7;
- Op0.Val->Uses.push_back(this); Op1.Val->Uses.push_back(this);
- Op2.Val->Uses.push_back(this); Op3.Val->Uses.push_back(this);
- Op4.Val->Uses.push_back(this); Op5.Val->Uses.push_back(this);
- Op6.Val->Uses.push_back(this);
- }
- void setOperands(SDOperand Op0, SDOperand Op1, SDOperand Op2, SDOperand Op3,
- SDOperand Op4, SDOperand Op5, SDOperand Op6, SDOperand Op7) {
- assert(NumOperands == 0 && "Should not have operands yet!");
- OperandList = new SDOperand[8];
- OperandList[0] = Op0;
- OperandList[1] = Op1;
- OperandList[2] = Op2;
- OperandList[3] = Op3;
- OperandList[4] = Op4;
- OperandList[5] = Op5;
- OperandList[6] = Op6;
- OperandList[7] = Op7;
- NumOperands = 8;
- Op0.Val->Uses.push_back(this); Op1.Val->Uses.push_back(this);
- Op2.Val->Uses.push_back(this); Op3.Val->Uses.push_back(this);
- Op4.Val->Uses.push_back(this); Op5.Val->Uses.push_back(this);
- Op6.Val->Uses.push_back(this); Op7.Val->Uses.push_back(this);
+ NumOperands = NumOps;
+ OperandList = new SDOperand[NumOperands];
+
+ for (unsigned i = 0, e = NumOps; i != e; ++i) {
+ OperandList[i] = Ops[i];
+ SDNode *N = OperandList[i].Val;
+ N->Uses.push_back(this);
+ }
}
void addUser(SDNode *User) {
inline const SDOperand &SDOperand::getOperand(unsigned i) const {
return Val->getOperand(i);
}
+inline uint64_t SDOperand::getConstantOperandVal(unsigned i) const {
+ return Val->getConstantOperandVal(i);
+}
inline bool SDOperand::isTargetOpcode() const {
return Val->isTargetOpcode();
}
};
class ConstantPoolSDNode : public SDNode {
- Constant *C;
- int Offset;
+ union {
+ Constant *ConstVal;
+ MachineConstantPoolValue *MachineCPVal;
+ } Val;
+ int Offset; // It's a MachineConstantPoolValue if top bit is set.
unsigned Alignment;
protected:
friend class SelectionDAG;
ConstantPoolSDNode(bool isTarget, Constant *c, MVT::ValueType VT,
int o=0)
: SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, VT),
- C(c), Offset(o), Alignment(0) {}
+ Offset(o), Alignment(0) {
+ assert((int)Offset >= 0 && "Offset is too large");
+ Val.ConstVal = c;
+ }
ConstantPoolSDNode(bool isTarget, Constant *c, MVT::ValueType VT, int o,
unsigned Align)
: SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, VT),
- C(c), Offset(o), Alignment(Align) {}
+ Offset(o), Alignment(Align) {
+ assert((int)Offset >= 0 && "Offset is too large");
+ Val.ConstVal = c;
+ }
+ ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v,
+ MVT::ValueType VT, int o=0)
+ : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, VT),
+ Offset(o), Alignment(0) {
+ assert((int)Offset >= 0 && "Offset is too large");
+ Val.MachineCPVal = v;
+ Offset |= 1 << (sizeof(unsigned)*8-1);
+ }
+ ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v,
+ MVT::ValueType VT, int o, unsigned Align)
+ : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, VT),
+ Offset(o), Alignment(Align) {
+ assert((int)Offset >= 0 && "Offset is too large");
+ Val.MachineCPVal = v;
+ Offset |= 1 << (sizeof(unsigned)*8-1);
+ }
public:
- Constant *get() const { return C; }
- int getOffset() const { return Offset; }
+ bool isMachineConstantPoolEntry() const {
+ return (int)Offset < 0;
+ }
+
+ Constant *getConstVal() const {
+ assert(!isMachineConstantPoolEntry() && "Wrong constantpool type");
+ return Val.ConstVal;
+ }
+
+ MachineConstantPoolValue *getMachineCPVal() const {
+ assert(isMachineConstantPoolEntry() && "Wrong constantpool type");
+ return Val.MachineCPVal;
+ }
+
+ int getOffset() const {
+ return Offset & ~(1 << (sizeof(unsigned)*8-1));
+ }
// Return the alignment of this constant pool object, which is either 0 (for
// default alignment) or log2 of the desired value.
unsigned getAlignment() const { return Alignment; }
+ const Type *getType() const;
+
static bool classof(const ConstantPoolSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::ConstantPool ||
}
};
+/// LoadSDNode - This class is used to represent ISD::LOAD nodes.
+///
+class LoadSDNode : public SDNode {
+ // AddrMode - unindexed, pre-indexed, post-indexed.
+ ISD::MemIndexedMode AddrMode;
+
+ // ExtType - non-ext, anyext, sext, zext.
+ ISD::LoadExtType ExtType;
+
+ // LoadedVT - VT of loaded value before extension.
+ MVT::ValueType LoadedVT;
+
+ // SrcValue - Memory location for alias analysis.
+ const Value *SrcValue;
+
+ // SVOffset - Memory location offset.
+ int SVOffset;
+
+ // Alignment - Alignment of memory location in bytes.
+ unsigned Alignment;
+
+ // IsVolatile - True if the load is volatile.
+ bool IsVolatile;
+protected:
+ friend class SelectionDAG;
+ LoadSDNode(SDOperand Chain, SDOperand Ptr, SDOperand Off,
+ ISD::MemIndexedMode AM, ISD::LoadExtType ETy, MVT::ValueType LVT,
+ const Value *SV, int O=0, unsigned Align=1, bool Vol=false)
+ : SDNode(ISD::LOAD, Chain, Ptr, Off),
+ AddrMode(AM), ExtType(ETy), LoadedVT(LVT), SrcValue(SV), SVOffset(O),
+ Alignment(Align), IsVolatile(Vol) {
+ assert((Off.getOpcode() == ISD::UNDEF || AddrMode != ISD::UNINDEXED) &&
+ "Only indexed load has a non-undef offset operand");
+ }
+public:
+
+ const SDOperand getChain() const { return getOperand(0); }
+ const SDOperand getBasePtr() const { return getOperand(1); }
+ const SDOperand getOffset() const { return getOperand(2); }
+ ISD::MemIndexedMode getAddressingMode() const { return AddrMode; }
+ ISD::LoadExtType getExtensionType() const { return ExtType; }
+ MVT::ValueType getLoadedVT() const { return LoadedVT; }
+ const Value *getSrcValue() const { return SrcValue; }
+ int getSrcValueOffset() const { return SVOffset; }
+ unsigned getAlignment() const { return Alignment; }
+ bool isVolatile() const { return IsVolatile; }
+
+ static bool classof(const LoadSDNode *) { return true; }
+ static bool classof(const SDNode *N) {
+ return N->getOpcode() == ISD::LOAD;
+ }
+};
+
+/// StoreSDNode - This class is used to represent ISD::STORE nodes.
+///
+class StoreSDNode : public SDNode {
+ // AddrMode - unindexed, pre-indexed, post-indexed.
+ ISD::MemIndexedMode AddrMode;
+
+ // IsTruncStore - True is the op does a truncation before store.
+ bool IsTruncStore;
+
+ // StoredVT - VT of the value after truncation.
+ MVT::ValueType StoredVT;
+
+ // SrcValue - Memory location for alias analysis.
+ const Value *SrcValue;
+
+ // SVOffset - Memory location offset.
+ int SVOffset;
+
+ // Alignment - Alignment of memory location in bytes.
+ unsigned Alignment;
+
+ // IsVolatile - True if the store is volatile.
+ bool IsVolatile;
+protected:
+ friend class SelectionDAG;
+ StoreSDNode(SDOperand Chain, SDOperand Value, SDOperand Ptr, SDOperand Off,
+ ISD::MemIndexedMode AM, bool isTrunc, MVT::ValueType SVT,
+ const Value *SV, int O=0, unsigned Align=0, bool Vol=false)
+ : SDNode(ISD::STORE, Chain, Value, Ptr, Off),
+ AddrMode(AM), IsTruncStore(isTrunc), StoredVT(SVT), SrcValue(SV),
+ SVOffset(O), Alignment(Align), IsVolatile(Vol) {
+ assert((Off.getOpcode() == ISD::UNDEF || AddrMode != ISD::UNINDEXED) &&
+ "Only indexed store has a non-undef offset operand");
+ }
+public:
+
+ const SDOperand getChain() const { return getOperand(0); }
+ const SDOperand getValue() const { return getOperand(1); }
+ const SDOperand getBasePtr() const { return getOperand(2); }
+ const SDOperand getOffset() const { return getOperand(3); }
+ ISD::MemIndexedMode getAddressingMode() const { return AddrMode; }
+ bool isTruncatingStore() const { return IsTruncStore; }
+ MVT::ValueType getStoredVT() const { return StoredVT; }
+ const Value *getSrcValue() const { return SrcValue; }
+ int getSrcValueOffset() const { return SVOffset; }
+ unsigned getAlignment() const { return Alignment; }
+ bool isVolatile() const { return IsVolatile; }
+
+ static bool classof(const StoreSDNode *) { return true; }
+ static bool classof(const SDNode *N) {
+ return N->getOpcode() == ISD::STORE;
+ }
+};
+
class SDNodeIterator : public forward_iterator<SDNode, ptrdiff_t> {
SDNode *Node;
const ilist_iterator<SDNode> &Y) {}
};
+namespace ISD {
+ /// isNON_EXTLoad - Returns true if the specified node is a non-extending
+ /// load.
+ inline bool isNON_EXTLoad(const SDNode *N) {
+ return N->getOpcode() == ISD::LOAD &&
+ cast<LoadSDNode>(N)->getExtensionType() == ISD::NON_EXTLOAD;
+ }
+
+ /// isEXTLoad - Returns true if the specified node is a EXTLOAD.
+ ///
+ inline bool isEXTLoad(const SDNode *N) {
+ return N->getOpcode() == ISD::LOAD &&
+ cast<LoadSDNode>(N)->getExtensionType() == ISD::EXTLOAD;
+ }
+
+ /// isSEXTLoad - Returns true if the specified node is a SEXTLOAD.
+ ///
+ inline bool isSEXTLoad(const SDNode *N) {
+ return N->getOpcode() == ISD::LOAD &&
+ cast<LoadSDNode>(N)->getExtensionType() == ISD::SEXTLOAD;
+ }
+
+ /// isZEXTLoad - Returns true if the specified node is a ZEXTLOAD.
+ ///
+ inline bool isZEXTLoad(const SDNode *N) {
+ return N->getOpcode() == ISD::LOAD &&
+ cast<LoadSDNode>(N)->getExtensionType() == ISD::ZEXTLOAD;
+ }
+
+ /// isNON_TRUNCStore - Returns true if the specified node is a non-truncating
+ /// store.
+ inline bool isNON_TRUNCStore(const SDNode *N) {
+ return N->getOpcode() == ISD::STORE &&
+ !cast<StoreSDNode>(N)->isTruncatingStore();
+ }
+
+ /// isTRUNCStore - Returns true if the specified node is a truncating
+ /// store.
+ inline bool isTRUNCStore(const SDNode *N) {
+ return N->getOpcode() == ISD::STORE &&
+ cast<StoreSDNode>(N)->isTruncatingStore();
+ }
+}
+
+
} // end llvm namespace
#endif