#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/RecyclingAllocator.h"
#include "llvm/Support/DataTypes.h"
-#include "llvm/CodeGen/DebugLoc.h"
+#include "llvm/Support/DebugLoc.h"
#include <cassert>
+#include <climits>
namespace llvm {
///
struct SDVTList {
const MVT *VTs;
- unsigned short NumVTs;
+ unsigned int NumVTs;
};
/// ISD namespace - This namespace contains an enum which represents all of the
/// and getMachineOpcode() member functions of SDNode.
///
enum NodeType {
- // DELETED_NODE - This is an illegal flag value that is used to catch
+ // DELETED_NODE - This is an illegal value that is used to catch
// errors. This opcode is not a legal opcode for any node.
DELETED_NODE,
-
+
// EntryToken - This is the marker used to indicate the start of the region.
EntryToken,
// single token result. This is used to represent the fact that the operand
// operators are independent of each other.
TokenFactor,
-
- // AssertSext, AssertZext - These nodes record if a register contains a
- // value that has already been zero or sign extended from a narrower type.
- // These nodes take two operands. The first is the node that has already
+
+ // AssertSext, AssertZext - These nodes record if a register contains a
+ // value that has already been zero or sign extended from a narrower type.
+ // These nodes take two operands. The first is the node that has already
// been extended, and the second is a value type node indicating the width
// of the extension
AssertSext, AssertZext,
// 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
// first (possible) on-stack argument. This is needed for correct stack
// adjustment during unwind.
FRAME_TO_ARGS_OFFSET,
-
+
// RESULT, OUTCHAIN = EXCEPTIONADDR(INCHAIN) - This node represents the
// address of the exception block on entry to an landing pad block.
EXCEPTIONADDR,
-
+
// RESULT, OUTCHAIN = EHSELECTION(INCHAIN, EXCEPTION) - This node represents
// the selection index of the exception thrown.
EHSELECTION,
// simplification of the constant.
TargetConstant,
TargetConstantFP,
-
+
// TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or
// anything else with this node, and this is valid in the target-specific
// dag, turning into a GlobalAddress operand.
TargetJumpTable,
TargetConstantPool,
TargetExternalSymbol,
-
+
/// RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...)
/// This node represents a target intrinsic function with no side effects.
/// The first operand is the ID number of the intrinsic from the
/// llvm::Intrinsic namespace. The operands to the intrinsic follow. The
/// node has returns the result of the intrinsic.
INTRINSIC_WO_CHAIN,
-
+
/// RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...)
/// This node represents a target intrinsic function with side effects that
/// returns a result. The first operand is a chain pointer. The second is
/// second is the ID number of the intrinsic from the llvm::Intrinsic
/// namespace. The operands to the intrinsic follow.
INTRINSIC_VOID,
-
+
// CopyToReg - This node has three operands: a chain, a register number to
- // set to this value, and a value.
+ // set to this value, and a value.
CopyToReg,
// CopyFromReg - This node indicates that the input value is a virtual or
// UNDEF - An undefined node
UNDEF,
-
+
/// 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
/// 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, CALLEE,
/// ARG0, FLAG0, ARG1, FLAG1, ... ARGn, FLAGn)
/// This node represents a fully general function call, before the legalizer
// SDIVREM/UDIVREM - Divide two integers and produce both a quotient and
// remainder result.
SDIVREM, UDIVREM,
-
+
// CARRY_FALSE - This node is used when folding other nodes,
// like ADDC/SUBC, which indicate the carry result is always false.
CARRY_FALSE,
-
+
// Carry-setting nodes for multiple precision addition and subtraction.
// These nodes take two operands of the same value type, and produce two
// results. The first result is the normal add or sub result, the second
// result is the carry flag result.
ADDC, SUBC,
-
+
// Carry-using nodes for multiple precision addition and subtraction. These
// nodes take three operands: The first two are the normal lhs and rhs to
// the add or sub, and the third is the input carry flag. These nodes
// INT = FGETSIGN(FP) - Return the sign bit of the specified floating point
// value as an integer 0/1 value.
FGETSIGN,
-
- /// BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a vector
- /// with the specified, possibly variable, elements. The number of elements
- /// is required to be a power of two.
+
+ /// BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a vector with the
+ /// specified, possibly variable, elements. The number of elements is
+ /// required to be a power of two. The types of the operands must all be
+ /// the same and must match the vector element type, except that integer
+ /// types are allowed to be larger than the element type, in which case
+ /// the operands are implicitly truncated.
BUILD_VECTOR,
-
+
/// INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element
/// at IDX replaced with VAL. If the type of VAL is larger than the vector
/// element type then VAL is truncated before replacement.
INSERT_VECTOR_ELT,
/// EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR
- /// identified by the (potentially variable) element number IDX.
+ /// identified by the (potentially variable) element number IDX. If the
+ /// return type is an integer type larger than the element type of the
+ /// vector, the result is extended to the width of the return type.
EXTRACT_VECTOR_ELT,
-
+
/// CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of
/// vector type with the same length and element type, this produces a
/// concatenated vector result value, with length equal to the sum of the
/// lengths of the input vectors.
CONCAT_VECTORS,
-
+
/// EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR (an
/// vector value) starting with the (potentially variable) element number
/// IDX, which must be a multiple of the result vector length.
EXTRACT_SUBVECTOR,
- /// VECTOR_SHUFFLE(VEC1, VEC2, SHUFFLEVEC) - Returns a vector, of the same
- /// type as VEC1/VEC2. SHUFFLEVEC is a BUILD_VECTOR of constant int values
- /// (maybe of an illegal datatype) or undef that indicate which value each
- /// result element will get. The elements of VEC1/VEC2 are enumerated in
- /// order. This is quite similar to the Altivec 'vperm' instruction, except
- /// that the indices must be constants and are in terms of the element size
- /// of VEC1/VEC2, not in terms of bytes.
+ /// VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as
+ /// VEC1/VEC2. A VECTOR_SHUFFLE node also contains an array of constant int
+ /// values that indicate which value (or undef) each result element will
+ /// get. These constant ints are accessible through the
+ /// ShuffleVectorSDNode class. This is quite similar to the Altivec
+ /// 'vperm' instruction, except that the indices must be constants and are
+ /// in terms of the element size of VEC1/VEC2, not in terms of bytes.
VECTOR_SHUFFLE,
/// SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a
/// scalar value into element 0 of the resultant vector type. The top
- /// elements 1 to N-1 of the N-element vector are undefined.
+ /// elements 1 to N-1 of the N-element vector are undefined. The type
+ /// of the operand must match the vector element type, except when they
+ /// are integer types. In this case the operand is allowed to be wider
+ /// than the vector element type, and is implicitly truncated to it.
SCALAR_TO_VECTOR,
-
- // EXTRACT_SUBREG - This node is used to extract a sub-register value.
- // This node takes a superreg and a constant sub-register index as operands.
- // Note sub-register indices must be increasing. That is, if the
- // sub-register index of a 8-bit sub-register is N, then the index for a
- // 16-bit sub-register must be at least N+1.
- EXTRACT_SUBREG,
-
- // INSERT_SUBREG - This node is used to insert a sub-register value.
- // This node takes a superreg, a subreg value, and a constant sub-register
- // index as operands.
- INSERT_SUBREG,
-
+
// MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing
// an unsigned/signed value of type i[2*N], then return the top part.
MULHU, MULHS,
// i1 then the high bits must conform to getBooleanContents.
SELECT,
- // Select with condition operator - This selects between a true value and
+ // Select with condition operator - This selects between a true value and
// a false value (ops #2 and #3) based on the boolean result of comparing
- // the lhs and rhs (ops #0 and #1) of a conditional expression with the
+ // the lhs and rhs (ops #0 and #1) of a conditional expression with the
// condition code in op #4, a CondCodeSDNode.
SELECT_CC,
// them with (op #2) as a CondCodeSDNode.
SETCC,
- // Vector SetCC operator - This evaluates to a vector of integer elements
- // with the high bit in each element set to true if the comparison is true
- // and false if the comparison is false. All other bits in each element
- // are undefined. The operands to this are the left and right operands
- // to compare (ops #0, and #1) and the condition code to compare them with
- // (op #2) as a CondCodeSDNode.
+ // RESULT = VSETCC(LHS, RHS, COND) operator - This evaluates to a vector of
+ // integer elements with all bits of the result elements set to true if the
+ // comparison is true or all cleared if the comparison is false. The
+ // operands to this are the left and right operands to compare (LHS/RHS) and
+ // the condition code to compare them with (COND) as a CondCodeSDNode.
VSETCC,
// SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded
// ANY_EXTEND - Used for integer types. The high bits are undefined.
ANY_EXTEND,
-
+
// TRUNCATE - Completely drop the high bits.
TRUNCATE,
/// The TRUNC = 1 case is used in cases where we know that the value will
/// not be modified by the node, because Y is not using any of the extra
/// precision of source type. This allows certain transformations like
- /// FP_EXTEND(FP_ROUND(X,1)) -> X which are not safe for
+ /// FP_EXTEND(FP_ROUND(X,1)) -> X which are not safe for
/// FP_EXTEND(FP_ROUND(X,0)) because the extra bits aren't removed.
FP_ROUND,
-
+
// FLT_ROUNDS_ - Returns current rounding mode:
// -1 Undefined
// 0 Round to 0
// BIT_CONVERT - Theis operator converts between integer and FP values, as
// if one was stored to memory as integer and the other was loaded from the
- // same address (or equivalently for vector format conversions, etc). The
- // source and result are required to have the same bit size (e.g.
- // f32 <-> i32). This can also be used for int-to-int or fp-to-fp
+ // same address (or equivalently for vector format conversions, etc). The
+ // source and result are required to have the same bit size (e.g.
+ // f32 <-> i32). This can also be used for int-to-int or fp-to-fp
// conversions, but that is a noop, deleted by getNode().
BIT_CONVERT,
-
+
// CONVERT_RNDSAT - This operator is used to support various conversions
// between various types (float, signed, unsigned and vectors of those
// types) with rounding and saturation. NOTE: Avoid using this operator as
// 4) saturation imm
// 5) ISD::CvtCode indicating the type of conversion to do
CONVERT_RNDSAT,
-
+
// FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW,
// FLOG, FLOG2, FLOG10, FEXP, FEXP2,
// FCEIL, FTRUNC, FRINT, FNEARBYINT, FFLOOR - Perform various unary floating
FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW,
FLOG, FLOG2, FLOG10, FEXP, FEXP2,
FCEIL, FTRUNC, FRINT, FNEARBYINT, FFLOOR,
-
+
// 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
// compare, rather than as a combined SetCC node. The operands in order are
// chain, cc, lhs, rhs, block to branch to if condition is true.
BR_CC,
-
+
// RET - Return from function. The first operand is the chain,
// and any subsequent operands are pairs of return value and return value
// attributes (see CALL for description of attributes) for the function.
// Operand #2n+3: A TargetConstant, indicating if the reg is a use/def
// Operand #last: Optional, an incoming flag.
INLINEASM,
-
+
// DBG_LABEL, EH_LABEL - Represents a label in mid basic block used to track
// locations needed for debug and exception handling tables. These nodes
// take a chain as input and return a chain.
// a chain, while the next two operands are first two arguments (address
// and variable) of a llvm.dbg.declare instruction.
DECLARE,
-
+
// 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
// chain.
STACKSAVE,
-
+
// STACKRESTORE has two operands, an input chain and a pointer to restore to
// it returns an output chain.
STACKRESTORE,
-
+
// CALLSEQ_START/CALLSEQ_END - These operators mark the beginning and end of
// a call sequence, and carry arbitrary information that target might want
// to know. The first operand is a chain, the rest are specified by the
// CALLSEQ_START..CALLSEQ_END pairs may not be nested.
CALLSEQ_START, // Beginning of a call sequence
CALLSEQ_END, // End of a call sequence
-
- // VAARG - VAARG has three operands: an input chain, a pointer, and a
+
+ // VAARG - VAARG has three operands: an input chain, a pointer, and a
// SRCVALUE. It returns a pair of values: the vaarg value and a new chain.
VAARG,
-
+
// VACOPY - VACOPY has five operands: an input chain, a destination pointer,
// a source pointer, a SRCVALUE for the destination, and a SRCVALUE for the
// source.
VACOPY,
-
+
// VAEND, VASTART - VAEND and VASTART have three operands: an input chain, a
// pointer, and a SRCVALUE.
VAEND, VASTART,
// READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
// The only operand is a chain and a value and a chain are produced. The
- // value is the contents of the architecture specific cycle counter like
+ // value is the contents of the architecture specific cycle counter like
// register (or other high accuracy low latency clock source)
READCYCLECOUNTER,
// column number, and a pointer to a CompileUnit object identifying
// the containing compilation unit. It produces a token chain as output.
DBG_STOPPOINT,
-
+
// 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 MachineModuleInfo.) It
// read / write specifier, and locality specifier.
PREFETCH,
- // OUTCHAIN = MEMBARRIER(INCHAIN, load-load, load-store, store-load,
+ // OUTCHAIN = MEMBARRIER(INCHAIN, load-load, load-store, store-load,
// store-store, device)
// This corresponds to the memory.barrier intrinsic.
// it takes an input chain, 4 operands to specify the type of barrier, an
ATOMIC_LOAD_MAX,
ATOMIC_LOAD_UMIN,
ATOMIC_LOAD_UMAX,
-
+
// BUILTIN_OP_END - This must be the last enum value in this list.
BUILTIN_OP_END
};
/// isDebugLabel - Return true if the specified node represents a debug
/// label (i.e. ISD::DBG_LABEL or TargetInstrInfo::DBG_LABEL node).
bool isDebugLabel(const SDNode *N);
-
+
//===--------------------------------------------------------------------===//
- /// MemIndexedMode enum - This enum defines the load / store indexed
+ /// MemIndexedMode enum - This enum defines the load / store indexed
/// addressing modes.
///
/// UNINDEXED "Normal" load / store. The effective address is already
/// 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,
+ /// 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].
///
CondCode getSetCCAndOperation(CondCode Op1, CondCode Op2, bool isInteger);
//===--------------------------------------------------------------------===//
- /// CvtCode enum - This enum defines the various converts CONVERT_RNDSAT
+ /// CvtCode enum - This enum defines the various converts CONVERT_RNDSAT
/// supports.
enum CvtCode {
CVT_FF, // Float from Float
inline unsigned getMachineOpcode() const;
inline const DebugLoc getDebugLoc() const;
-
+
/// reachesChainWithoutSideEffects - Return true if this operand (which must
- /// be a chain) reaches the specified operand without crossing any
+ /// be a chain) reaches the specified operand without crossing any
/// side-effecting instructions. In practice, this looks through token
/// factors and non-volatile loads. In order to remain efficient, this only
/// looks a couple of nodes in, it does not do an exhaustive search.
- bool reachesChainWithoutSideEffects(SDValue Dest,
+ bool reachesChainWithoutSideEffects(SDValue Dest,
unsigned Depth = 2) const;
-
+
/// use_empty - Return true if there are no nodes using value ResNo
/// of Node.
///
template<> struct DenseMapInfo<SDValue> {
- static inline SDValue getEmptyKey() {
- return SDValue((SDNode*)-1, -1U);
+ static inline SDValue getEmptyKey() {
+ return SDValue((SDNode*)-1, -1U);
}
- static inline SDValue getTombstoneKey() {
+ static inline SDValue getTombstoneKey() {
return SDValue((SDNode*)-1, 0);
}
static unsigned getHashValue(const SDValue &Val) {
SDValue Val;
/// User - The user of this value.
SDNode *User;
- /// Prev, Next - Pointers to the uses list of the SDNode referred by
+ /// Prev, Next - Pointers to the uses list of the SDNode referred by
/// this operand.
SDUse **Prev, *Next;
/// If implicit conversion to SDValue doesn't work, the get() method returns
/// the SDValue.
const SDValue &get() const { return Val; }
-
+
/// getUser - This returns the SDNode that contains this Use.
SDNode *getUser() { return User; }
bool operator==(const SDValue &V) const {
return Val == V;
}
-
+
/// operator!= - Convenience function for get().operator!=
bool operator!=(const SDValue &V) const {
return Val != V;
/// NodeType - The operation that this node performs.
///
short NodeType;
-
+
/// OperandsNeedDelete - This is true if OperandList was new[]'d. If true,
/// then they will be delete[]'d when the node is destroyed.
unsigned short OperandsNeedDelete : 1;
/// OperandList - The values that are used by this operation.
///
SDUse *OperandList;
-
+
/// ValueList - The types of the values this node defines. SDNode's may
/// define multiple values simultaneously.
const MVT *ValueList;
unsigned getOpcode() const { return (unsigned short)NodeType; }
/// isTargetOpcode - Test if this node has a target-specific opcode (in the
- /// <target>ISD namespace).
+ /// \<target\>ISD namespace).
bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; }
/// isMachineOpcode - Test if this node has a post-isel opcode, directly
void setDebugLoc(const DebugLoc dl) { debugLoc = dl; }
/// use_iterator - This class provides iterator support for SDUse
- /// operands that use a specific SDNode.
+ /// operands that use a specific SDNode.
class use_iterator
: public forward_iterator<SDUse, ptrdiff_t> {
SDUse *Op;
bool operator!=(const use_iterator &x) const {
return !operator==(x);
}
-
+
/// atEnd - return true if this iterator is at the end of uses list.
bool atEnd() const { return Op == 0; }
///
unsigned getNumOperands() const { return NumOperands; }
- /// getConstantOperandVal - Helper method returns the integer value of a
+ /// getConstantOperandVal - Helper method returns the integer value of a
/// ConstantSDNode operand.
uint64_t getConstantOperandVal(unsigned Num) const;
return Ret;
}
- SDNode(unsigned Opc, const DebugLoc dl, SDVTList VTs, const SDValue *Ops,
+ SDNode(unsigned Opc, const DebugLoc dl, SDVTList VTs, const SDValue *Ops,
unsigned NumOps)
: NodeType(Opc), OperandsNeedDelete(true), SubclassData(0),
NodeId(-1),
NodeId(-1), OperandList(0), ValueList(VTs.VTs), UseList(NULL),
NumOperands(0), NumValues(VTs.NumVTs),
debugLoc(dl) {}
-
+
/// InitOperands - Initialize the operands list of this with 1 operand.
void InitOperands(SDUse *Ops, const SDValue &Op0) {
Ops[0].setUser(this);
getSDVTList(MVT::Other)) {
InitOperands(&Op, X);
}
- ~HandleSDNode();
+ ~HandleSDNode();
const SDValue &getValue() const { return Op; }
};
}
};
+/// ShuffleVectorSDNode - This SDNode is used to implement the code generator
+/// support for the llvm IR shufflevector instruction. It combines elements
+/// from two input vectors into a new input vector, with the selection and
+/// ordering of elements determined by an array of integers, referred to as
+/// the shuffle mask. For input vectors of width N, mask indices of 0..N-1
+/// refer to elements from the LHS input, and indices from N to 2N-1 the RHS.
+/// 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(MVT VT, DebugLoc dl, SDValue N1, SDValue N2,
+ const int *M)
+ : SDNode(ISD::VECTOR_SHUFFLE, dl, getSDVTList(VT)), Mask(M) {
+ InitOperands(Ops, N1, N2);
+ }
+public:
+
+ void getMask(SmallVectorImpl<int> &M) const {
+ MVT VT = getValueType(0);
+ M.clear();
+ for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i)
+ M.push_back(Mask[i]);
+ }
+ 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!");
+ return Mask[0];
+ }
+ static bool isSplatMask(const int *Mask, MVT VT);
+
+ static bool classof(const ShuffleVectorSDNode *) { return true; }
+ static bool classof(const SDNode *N) {
+ return N->getOpcode() == ISD::VECTOR_SHUFFLE;
+ }
+};
+
class ConstantSDNode : public SDNode {
const ConstantInt *Value;
-protected:
friend class SelectionDAG;
ConstantSDNode(bool isTarget, const ConstantInt *val, MVT VT)
- : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant,
+ : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant,
DebugLoc::getUnknownLoc(), getSDVTList(VT)), Value(val) {
}
public:
class ConstantFPSDNode : public SDNode {
const ConstantFP *Value;
-protected:
friend class SelectionDAG;
ConstantFPSDNode(bool isTarget, const ConstantFP *val, MVT VT)
: SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP,
/// two floating point values.
/// We leave the version with the double argument here because it's just so
- /// convenient to write "2.0" and the like. Without this function we'd
+ /// convenient to write "2.0" and the like. Without this function we'd
/// have to duplicate its logic everywhere it's called.
bool isExactlyValue(double V) const {
bool ignored;
static bool classof(const ConstantFPSDNode *) { return true; }
static bool classof(const SDNode *N) {
- return N->getOpcode() == ISD::ConstantFP ||
+ return N->getOpcode() == ISD::ConstantFP ||
N->getOpcode() == ISD::TargetConstantFP;
}
};
class GlobalAddressSDNode : public SDNode {
GlobalValue *TheGlobal;
int64_t Offset;
-protected:
+ unsigned char TargetFlags;
friend class SelectionDAG;
- GlobalAddressSDNode(bool isTarget, const GlobalValue *GA, MVT VT,
- int64_t o = 0);
+ GlobalAddressSDNode(unsigned Opc, const GlobalValue *GA, MVT VT,
+ int64_t o, unsigned char TargetFlags);
public:
GlobalValue *getGlobal() const { return TheGlobal; }
int64_t getOffset() const { return Offset; }
+ unsigned char getTargetFlags() const { return TargetFlags; }
+ // Return the address space this GlobalAddress belongs to.
+ unsigned getAddressSpace() const;
static bool classof(const GlobalAddressSDNode *) { return true; }
static bool classof(const SDNode *N) {
class FrameIndexSDNode : public SDNode {
int FI;
-protected:
friend class SelectionDAG;
FrameIndexSDNode(int fi, MVT VT, bool isTarg)
- : SDNode(isTarg ? ISD::TargetFrameIndex : ISD::FrameIndex,
+ : SDNode(isTarg ? ISD::TargetFrameIndex : ISD::FrameIndex,
DebugLoc::getUnknownLoc(), getSDVTList(VT)), FI(fi) {
}
public:
class JumpTableSDNode : public SDNode {
int JTI;
-protected:
+ unsigned char TargetFlags;
friend class SelectionDAG;
- JumpTableSDNode(int jti, MVT VT, bool isTarg)
+ JumpTableSDNode(int jti, MVT VT, bool isTarg, unsigned char TF)
: SDNode(isTarg ? ISD::TargetJumpTable : ISD::JumpTable,
- DebugLoc::getUnknownLoc(), getSDVTList(VT)), JTI(jti) {
+ DebugLoc::getUnknownLoc(), getSDVTList(VT)), JTI(jti), TargetFlags(TF) {
}
public:
-
+
int getIndex() const { return JTI; }
-
+ unsigned char getTargetFlags() const { return TargetFlags; }
+
static bool classof(const JumpTableSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::JumpTable ||
MachineConstantPoolValue *MachineCPVal;
} Val;
int Offset; // It's a MachineConstantPoolValue if top bit is set.
- unsigned Alignment;
-protected:
+ unsigned Alignment; // Minimum alignment requirement of CP (not log2 value).
+ unsigned char TargetFlags;
friend class SelectionDAG;
- ConstantPoolSDNode(bool isTarget, Constant *c, MVT VT, int o=0)
- : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool,
- DebugLoc::getUnknownLoc(),
- getSDVTList(VT)), Offset(o), Alignment(0) {
- assert((int)Offset >= 0 && "Offset is too large");
- Val.ConstVal = c;
- }
- ConstantPoolSDNode(bool isTarget, Constant *c, MVT VT, int o, unsigned Align)
+ ConstantPoolSDNode(bool isTarget, Constant *c, MVT VT, int o, unsigned Align,
+ unsigned char TF)
: SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool,
DebugLoc::getUnknownLoc(),
- getSDVTList(VT)), Offset(o), Alignment(Align) {
+ getSDVTList(VT)), Offset(o), Alignment(Align), TargetFlags(TF) {
assert((int)Offset >= 0 && "Offset is too large");
Val.ConstVal = c;
}
ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v,
- MVT VT, int o=0)
- : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool,
- DebugLoc::getUnknownLoc(),
- getSDVTList(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 VT, int o, unsigned Align)
+ MVT VT, int o, unsigned Align, unsigned char TF)
: SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool,
DebugLoc::getUnknownLoc(),
- getSDVTList(VT)), Offset(o), Alignment(Align) {
+ getSDVTList(VT)), Offset(o), Alignment(Align), TargetFlags(TF) {
assert((int)Offset >= 0 && "Offset is too large");
Val.MachineCPVal = v;
- Offset |= 1 << (sizeof(unsigned)*8-1);
+ Offset |= 1 << (sizeof(unsigned)*CHAR_BIT-1);
}
public:
+
bool isMachineConstantPoolEntry() const {
return (int)Offset < 0;
}
int getOffset() const {
- return Offset & ~(1 << (sizeof(unsigned)*8-1));
+ return Offset & ~(1 << (sizeof(unsigned)*CHAR_BIT-1));
}
-
+
// Return the alignment of this constant pool object, which is either 0 (for
- // default alignment) or log2 of the desired value.
+ // default alignment) or the desired value.
unsigned getAlignment() const { return Alignment; }
+ unsigned char getTargetFlags() const { return TargetFlags; }
const Type *getType() const;
class BasicBlockSDNode : public SDNode {
MachineBasicBlock *MBB;
-protected:
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
}
};
+/// BuildVectorSDNode - A "pseudo-class" with methods for operating on
+/// BUILD_VECTORs.
+class BuildVectorSDNode : public SDNode {
+ // These are constructed as SDNodes and then cast to BuildVectorSDNodes.
+ explicit BuildVectorSDNode(); // Do not implement
+public:
+ /// isConstantSplat - Check if this is a constant splat, and if so, find the
+ /// smallest element size that splats the vector. If MinSplatBits is
+ /// nonzero, the element size must be at least that large. Note that the
+ /// splat element may be the entire vector (i.e., a one element vector).
+ /// Returns the splat element value in SplatValue. Any undefined bits in
+ /// that value are zero, and the corresponding bits in the SplatUndef mask
+ /// are set. The SplatBitSize value is set to the splat element size in
+ /// bits. HasAnyUndefs is set to true if any bits in the vector are
+ /// undefined.
+ bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef,
+ unsigned &SplatBitSize, bool &HasAnyUndefs,
+ unsigned MinSplatBits = 0);
+
+ static inline bool classof(const BuildVectorSDNode *) { return true; }
+ static inline bool classof(const SDNode *N) {
+ return N->getOpcode() == ISD::BUILD_VECTOR;
+ }
+};
+
/// SrcValueSDNode - An SDNode that holds an arbitrary LLVM IR Value. This is
/// used when the SelectionDAG needs to make a simple reference to something
/// in the LLVM IR representation.
///
class SrcValueSDNode : public SDNode {
const Value *V;
-protected:
friend class SelectionDAG;
/// Create a SrcValue for a general value.
explicit SrcValueSDNode(const Value *v)
/// and ISD::STORE have been lowered.
///
class MemOperandSDNode : public SDNode {
-protected:
friend class SelectionDAG;
/// Create a MachineMemOperand node
explicit MemOperandSDNode(const MachineMemOperand &mo)
class RegisterSDNode : public SDNode {
unsigned Reg;
-protected:
friend class SelectionDAG;
RegisterSDNode(unsigned reg, MVT VT)
: SDNode(ISD::Register, DebugLoc::getUnknownLoc(),
unsigned Line;
unsigned Column;
Value *CU;
-protected:
friend class SelectionDAG;
DbgStopPointSDNode(SDValue ch, unsigned l, unsigned c,
Value *cu)
class LabelSDNode : public SDNode {
SDUse Chain;
unsigned LabelID;
-protected:
friend class SelectionDAG;
LabelSDNode(unsigned NodeTy, DebugLoc dl, SDValue ch, unsigned id)
: SDNode(NodeTy, dl, getSDVTList(MVT::Other)), LabelID(id) {
class ExternalSymbolSDNode : public SDNode {
const char *Symbol;
-protected:
+ unsigned char TargetFlags;
+
friend class SelectionDAG;
- ExternalSymbolSDNode(bool isTarget, const char *Sym, MVT VT)
+ ExternalSymbolSDNode(bool isTarget, const char *Sym, unsigned char TF, MVT VT)
: SDNode(isTarget ? ISD::TargetExternalSymbol : ISD::ExternalSymbol,
DebugLoc::getUnknownLoc(),
- getSDVTList(VT)), Symbol(Sym) {
+ getSDVTList(VT)), Symbol(Sym), TargetFlags(TF) {
}
public:
const char *getSymbol() const { return Symbol; }
+ unsigned char getTargetFlags() const { return TargetFlags; }
static bool classof(const ExternalSymbolSDNode *) { return true; }
static bool classof(const SDNode *N) {
class CondCodeSDNode : public SDNode {
ISD::CondCode Condition;
-protected:
friend class SelectionDAG;
explicit CondCodeSDNode(ISD::CondCode Cond)
: SDNode(ISD::CONDCODE, DebugLoc::getUnknownLoc(),
return N->getOpcode() == ISD::CONDCODE;
}
};
-
+
/// CvtRndSatSDNode - NOTE: avoid using this node as this may disappear in the
/// future and most targets don't support it.
class CvtRndSatSDNode : public SDNode {
ISD::CvtCode CvtCode;
-protected:
friend class SelectionDAG;
explicit CvtRndSatSDNode(MVT VT, DebugLoc dl, const SDValue *Ops,
unsigned NumOps, ISD::CvtCode Code)
- : SDNode(ISD::CONVERT_RNDSAT, dl, getSDVTList(VT), Ops, NumOps),
+ : SDNode(ISD::CONVERT_RNDSAT, dl, getSDVTList(VT), Ops, NumOps),
CvtCode(Code) {
assert(NumOps == 5 && "wrong number of operations");
}
void setNest() { Flags |= One << NestOffs; }
unsigned getByValAlign() const {
- return (unsigned)
+ return (unsigned)
((One << ((Flags & ByValAlign) >> ByValAlignOffs)) / 2);
}
void setByValAlign(unsigned A) {
Flags = (Flags & ~ByValAlign) |
(uint64_t(Log2_32(A) + 1) << ByValAlignOffs);
}
-
+
bool isSplit() const { return Flags & Split; }
void setSplit() { Flags |= One << SplitOffs; }
/// ARG_FLAGSSDNode - Leaf node holding parameter flags.
class ARG_FLAGSSDNode : public SDNode {
ISD::ArgFlagsTy TheFlags;
-protected:
friend class SelectionDAG;
explicit ARG_FLAGSSDNode(ISD::ArgFlagsTy Flags)
: SDNode(ISD::ARG_FLAGS, DebugLoc::getUnknownLoc(),
unsigned CallingConv;
bool IsVarArg;
bool IsTailCall;
+ unsigned NumFixedArgs;
// We might eventually want a full-blown Attributes for the result; that
// will expand the size of the representation. At the moment we only
// need Inreg.
bool Inreg;
-protected:
friend class SelectionDAG;
- CallSDNode(unsigned cc, DebugLoc dl, bool isvararg, bool istailcall,
- bool isinreg, SDVTList VTs, const SDValue *Operands,
- unsigned numOperands)
+ CallSDNode(unsigned cc, DebugLoc dl, bool isvararg, bool istailcall,
+ bool isinreg, SDVTList VTs, const SDValue *Operands,
+ unsigned numOperands, unsigned numFixedArgs)
: SDNode(ISD::CALL, dl, VTs, Operands, numOperands),
CallingConv(cc), IsVarArg(isvararg), IsTailCall(istailcall),
- Inreg(isinreg) {}
+ NumFixedArgs(numFixedArgs), Inreg(isinreg) {}
public:
unsigned getCallingConv() const { return CallingConv; }
unsigned isVarArg() const { return IsVarArg; }
SDValue getCallee() const { return getOperand(1); }
unsigned getNumArgs() const { return (getNumOperands() - 2) / 2; }
+ unsigned getNumFixedArgs() const {
+ if (isVarArg())
+ return NumFixedArgs;
+ else
+ return getNumArgs();
+ }
SDValue getArg(unsigned i) const { return getOperand(2+2*i); }
SDValue getArgFlagsVal(unsigned i) const {
return getOperand(3+2*i);
/// to parameterize some operations.
class VTSDNode : public SDNode {
MVT ValueType;
-protected:
friend class SelectionDAG;
explicit VTSDNode(MVT VT)
: SDNode(ISD::VALUETYPE, DebugLoc::getUnknownLoc(),
/// LSBaseSDNode - Base class for LoadSDNode and StoreSDNode
///
class LSBaseSDNode : public MemSDNode {
-protected:
//! Operand array for load and store
/*!
\note Moving this array to the base class captures more
/// LoadSDNode - This class is used to represent ISD::LOAD nodes.
///
class LoadSDNode : public LSBaseSDNode {
-protected:
friend class SelectionDAG;
LoadSDNode(SDValue *ChainPtrOff, DebugLoc dl, SDVTList VTs,
ISD::MemIndexedMode AM, ISD::LoadExtType ETy, MVT LVT,
/// StoreSDNode - This class is used to represent ISD::STORE nodes.
///
class StoreSDNode : public LSBaseSDNode {
-protected:
friend class SelectionDAG;
StoreSDNode(SDValue *ChainValuePtrOff, DebugLoc dl, SDVTList VTs,
ISD::MemIndexedMode AM, bool isTrunc, MVT SVT,