X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FCodeGen%2FSelectionDAGNodes.h;h=d4aa78211f74c5aaea6baea571784c7c9c6d2c15;hb=3c7b3fecacee40df7b9a99d290638398b5a62173;hp=a5fb08f32a713f41ac7f1d8b0204c101b787a324;hpb=824598883513789516a919651f4b35e7a638ec5c;p=oota-llvm.git diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index a5fb08f32a7..d4aa78211f7 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -22,18 +22,16 @@ #include "llvm/Constants.h" #include "llvm/ADT/FoldingSet.h" #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/ISDOpcodes.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/Support/MathExtras.h" +#include "llvm/System/DataTypes.h" #include "llvm/Support/DebugLoc.h" #include -#include namespace llvm { @@ -43,10 +41,13 @@ class MachineBasicBlock; class MachineConstantPoolValue; class SDNode; class Value; +class MCSymbol; template struct DenseMapInfo; template struct simplify_type; template struct ilist_traits; +void checkForCycles(const SDNode *N); + /// SDVTList - This represents a list of ValueType's that has been intern'd by /// a SelectionDAG. Instances of this simple value class are returned by /// SelectionDAG::getVTList(...). @@ -56,571 +57,7 @@ struct SDVTList { unsigned int NumVTs; }; -/// ISD namespace - This namespace contains an enum which represents all of the -/// SelectionDAG node types and value types. -/// namespace ISD { - - //===--------------------------------------------------------------------===// - /// ISD::NodeType enum - This enum defines the target-independent operators - /// for a SelectionDAG. - /// - /// Targets may also define target-dependent operator codes for SDNodes. For - /// example, on x86, these are the enum values in the X86ISD namespace. - /// Targets should aim to use target-independent operators to model their - /// instruction sets as much as possible, and only use target-dependent - /// operators when they have special requirements. - /// - /// Finally, during and after selection proper, SNodes may use special - /// operator codes that correspond directly with MachineInstr opcodes. These - /// are used to represent selected instructions. See the isMachineOpcode() - /// and getMachineOpcode() member functions of SDNode. - /// - enum NodeType { - // 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, - - // TokenFactor - This node takes multiple tokens as input and produces a - // 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 - // been extended, and the second is a value type node indicating the width - // of the extension - AssertSext, AssertZext, - - // Various leaf nodes. - BasicBlock, VALUETYPE, CONDCODE, Register, - Constant, ConstantFP, - GlobalAddress, GlobalTLSAddress, 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, - - // FRAME_TO_ARGS_OFFSET - This node represents offset from frame pointer to - // 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 = LSDAADDR(INCHAIN) - This node represents the - // address of the Language Specific Data Area for the enclosing function. - LSDAADDR, - - // RESULT, OUTCHAIN = EHSELECTION(INCHAIN, EXCEPTION) - This node represents - // the selection index of the exception thrown. - EHSELECTION, - - // OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER) - This node represents - // 'eh_return' gcc dwarf builtin, which is used to return from - // exception. The general meaning is: adjust stack by OFFSET and pass - // execution to HANDLER. Many platform-related details also :) - EH_RETURN, - - // TargetConstant* - Like Constant*, but the DAG does not do any folding or - // 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. - TargetGlobalAddress, - TargetGlobalTLSAddress, - TargetFrameIndex, - 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 - /// the ID number of the intrinsic from the llvm::Intrinsic namespace. The - /// operands to the intrinsic follow. The node has two results, the result - /// of the intrinsic and an output chain. - INTRINSIC_W_CHAIN, - - /// OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) - /// This node represents a target intrinsic function with side effects that - /// does not return a result. The first operand is a chain pointer. The - /// 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. - CopyToReg, - - // CopyFromReg - This node indicates that the input value is a virtual or - // physical register that is defined outside of the scope of this - // SelectionDAG. The register is available from the RegisterSDNode object. - CopyFromReg, - - // UNDEF - An undefined node - UNDEF, - - // EXTRACT_ELEMENT - This is used to get the lower or upper (determined by - // a Constant, which is required to be operand #1) half of the integer or - // float value specified as operand #0. This is only for use before - // legalization, for values that will be broken into multiple registers. - EXTRACT_ELEMENT, - - // BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways. Given - // two values of the same integer value type, this produces a value twice as - // big. Like EXTRACT_ELEMENT, this can only be used before legalization. - BUILD_PAIR, - - // MERGE_VALUES - This node takes multiple discrete operands and returns - // them all as its individual results. This nodes has exactly the same - // number of inputs and outputs. This node is useful for some pieces of the - // code generator that want to think about a single node with multiple - // results, not multiple nodes. - MERGE_VALUES, - - // Simple integer binary arithmetic operators. - ADD, SUB, MUL, SDIV, UDIV, SREM, UREM, - - // SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing - // a signed/unsigned value of type i[2*N], and return the full value as - // two results, each of type iN. - SMUL_LOHI, UMUL_LOHI, - - // 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 - // produce two results; the normal result of the add or sub, and the output - // carry flag. These nodes both read and write a carry flag to allow them - // to them to be chained together for add and sub of arbitrarily large - // values. - ADDE, SUBE, - - // RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition. - // These nodes take two operands: the normal LHS and RHS to the add. They - // produce two results: the normal result of the add, and a boolean that - // indicates if an overflow occured (*not* a flag, because it may be stored - // to memory, etc.). If the type of the boolean is not i1 then the high - // bits conform to getBooleanContents. - // These nodes are generated from the llvm.[su]add.with.overflow intrinsics. - SADDO, UADDO, - - // Same for subtraction - SSUBO, USUBO, - - // Same for multiplication - SMULO, UMULO, - - // Simple binary floating point operators. - FADD, FSUB, FMUL, FDIV, FREM, - - // FCOPYSIGN(X, Y) - Return the value of X with the sign of Y. NOTE: This - // DAG node does not require that X and Y have the same type, just that they - // are both floating point. X and the result must have the same type. - // FCOPYSIGN(f32, f64) is allowed. - FCOPYSIGN, - - // 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. 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. 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) - 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. 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, - - // 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, - - // Bitwise operators - logical and, logical or, logical xor, shift left, - // shift right algebraic (shift in sign bits), shift right logical (shift in - // zeroes), rotate left, rotate right, and byteswap. - AND, OR, XOR, SHL, SRA, SRL, ROTL, ROTR, BSWAP, - - // Counting operators - CTTZ, CTLZ, CTPOP, - - // Select(COND, TRUEVAL, FALSEVAL). If the type of the boolean COND is not - // i1 then the high bits must conform to getBooleanContents. - SELECT, - - // 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 - // condition code in op #4, a CondCodeSDNode. - SELECT_CC, - - // SetCC operator - This evaluates to a true value iff the condition is - // true. If the result value type is not i1 then the high bits conform - // to getBooleanContents. 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. - SETCC, - - // 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 - // integer shift operations, just like ADD/SUB_PARTS. The operation - // ordering is: - // [Lo,Hi] = op [LoLHS,HiLHS], Amt - SHL_PARTS, SRA_PARTS, SRL_PARTS, - - // Conversion operators. These are all single input single output - // operations. For all of these, the result type must be strictly - // wider or narrower (depending on the operation) than the source - // type. - - // SIGN_EXTEND - Used for integer types, replicating the sign bit - // into new bits. - SIGN_EXTEND, - - // ZERO_EXTEND - Used for integer types, zeroing the new bits. - ZERO_EXTEND, - - // ANY_EXTEND - Used for integer types. The high bits are undefined. - ANY_EXTEND, - - // TRUNCATE - Completely drop the high bits. - TRUNCATE, - - // [SU]INT_TO_FP - These operators convert integers (whose interpreted sign - // depends on the first letter) to floating point. - SINT_TO_FP, - UINT_TO_FP, - - // SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to - // sign extend a small value in a large integer register (e.g. sign - // extending the low 8 bits of a 32-bit register to fill the top 24 bits - // with the 7th bit). The size of the smaller type is indicated by the 1th - // operand, a ValueType node. - SIGN_EXTEND_INREG, - - /// FP_TO_[US]INT - Convert a floating point value to a signed or unsigned - /// integer. - FP_TO_SINT, - FP_TO_UINT, - - /// X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type - /// down to the precision of the destination VT. TRUNC is a flag, which is - /// always an integer that is zero or one. If TRUNC is 0, this is a - /// normal rounding, if it is 1, this FP_ROUND is known to not change the - /// value of Y. - /// - /// 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,0)) because the extra bits aren't removed. - FP_ROUND, - - // FLT_ROUNDS_ - Returns current rounding mode: - // -1 Undefined - // 0 Round to 0 - // 1 Round to nearest - // 2 Round to +inf - // 3 Round to -inf - FLT_ROUNDS_, - - /// X = FP_ROUND_INREG(Y, VT) - This operator takes an FP register, and - /// rounds it to a floating point value. It then promotes it and returns it - /// in a register of the same size. This operation effectively just - /// discards excess precision. The type to round down to is specified by - /// the VT operand, a VTSDNode. - FP_ROUND_INREG, - - /// X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type. - FP_EXTEND, - - // 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 - // 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 - // most target don't support it and the operator might be removed in the - // future. It takes the following arguments: - // 0) value - // 1) dest type (type to convert to) - // 2) src type (type to convert from) - // 3) rounding imm - // 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 - // point operations. These are inspired by libm. - 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 - // indexed memory ops). - LOAD, STORE, - - // DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned - // to a specified boundary. This node always has two return values: a new - // stack pointer value and a chain. The first operand is the token chain, - // the second is the number of bytes to allocate, and the third is the - // alignment boundary. The size is guaranteed to be a multiple of the stack - // alignment, and the alignment is guaranteed to be bigger than the stack - // alignment (if required) or 0 to get standard stack alignment. - DYNAMIC_STACKALLOC, - - // Control flow instructions. These all have token chains. - - // BR - Unconditional branch. The first operand is the chain - // operand, the second is the MBB to branch to. - BR, - - // BRIND - Indirect branch. The first operand is the chain, the second - // 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 to if the - // condition is true. If the type of the condition is not i1, then the - // high bits must conform to getBooleanContents. - BRCOND, - - // BR_CC - Conditional branch. The behavior is like that of SELECT_CC, in - // that the condition is represented as condition code, and two nodes to - // 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, - - // INLINEASM - Represents an inline asm block. This node always has two - // return values: a chain and a flag result. The inputs are as follows: - // Operand #0 : Input chain. - // Operand #1 : a ExternalSymbolSDNode with a pointer to the asm string. - // Operand #2n+2: A RegisterNode. - // 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. - DBG_LABEL, - EH_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 - // 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 - // target and not touched by the DAG optimizers. - // 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 - // 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, - - // SRCVALUE - This is a node type that holds a Value* that is used to - // make reference to a value in the LLVM IR. - SRCVALUE, - - // MEMOPERAND - This is a node that contains a MachineMemOperand which - // records information about a memory reference. This is used to make - // AliasAnalysis queries from the backend. - MEMOPERAND, - - // PCMARKER - This corresponds to the pcmarker intrinsic. - PCMARKER, - - // 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 - // register (or other high accuracy low latency clock source) - READCYCLECOUNTER, - - // HANDLENODE node - Used as a handle for various purposes. - HANDLENODE, - - // DBG_STOPPOINT - This node is used to represent a source location for - // debug info. It takes token chain as input, and carries a line number, - // 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 - // produces a token chain as output. - DEBUG_LOC, - - // TRAMPOLINE - This corresponds to the init_trampoline intrinsic. - // It takes as input a token chain, the pointer to the trampoline, - // the pointer to the nested function, the pointer to pass for the - // 'nest' parameter, a SRCVALUE for the trampoline and another for - // the nested function (allowing targets to access the original - // Function*). It produces the result of the intrinsic and a token - // chain as output. - TRAMPOLINE, - - // TRAP - Trapping instruction - TRAP, - - // PREFETCH - This corresponds to a prefetch intrinsic. It takes chains are - // their first operand. The other operands are the address to prefetch, - // read / write specifier, and locality specifier. - PREFETCH, - - // 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 - // operand specifying if the barrier applies to device and uncached memory - // and produces an output chain. - MEMBARRIER, - - // Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) - // this corresponds to the atomic.lcs intrinsic. - // cmp is compared to *ptr, and if equal, swap is stored in *ptr. - // the return is always the original value in *ptr - ATOMIC_CMP_SWAP, - - // Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) - // this corresponds to the atomic.swap intrinsic. - // amt is stored to *ptr atomically. - // the return is always the original value in *ptr - ATOMIC_SWAP, - - // Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN, ptr, amt) - // this corresponds to the atomic.load.[OpName] intrinsic. - // op(*ptr, amt) is stored to *ptr atomically. - // the return is always the original value in *ptr - ATOMIC_LOAD_ADD, - ATOMIC_LOAD_SUB, - ATOMIC_LOAD_AND, - ATOMIC_LOAD_OR, - ATOMIC_LOAD_XOR, - ATOMIC_LOAD_NAND, - ATOMIC_LOAD_MIN, - 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 - }; - /// Node predicates /// isBuildVectorAllOnes - Return true if the specified node is a @@ -635,178 +72,7 @@ namespace ISD { /// ISD::SCALAR_TO_VECTOR node or a BUILD_VECTOR node where only the low /// element is not an undef. bool isScalarToVector(const SDNode *N); - - /// 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 - /// 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 produce 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_LOADEXT_TYPE - }; - - //===--------------------------------------------------------------------===// - /// ISD::CondCode enum - These are ordered carefully to make the bitfields - /// below work out, when considering SETFALSE (something that never exists - /// dynamically) as 0. "U" -> Unsigned (for integer operands) or Unordered - /// (for floating point), "L" -> Less than, "G" -> Greater than, "E" -> Equal - /// to. If the "N" column is 1, the result of the comparison is undefined if - /// the input is a NAN. - /// - /// All of these (except for the 'always folded ops') should be handled for - /// floating point. For integer, only the SETEQ,SETNE,SETLT,SETLE,SETGT, - /// SETGE,SETULT,SETULE,SETUGT, and SETUGE opcodes are used. - /// - /// Note that these are laid out in a specific order to allow bit-twiddling - /// to transform conditions. - enum CondCode { - // Opcode N U L G E Intuitive operation - SETFALSE, // 0 0 0 0 Always false (always folded) - SETOEQ, // 0 0 0 1 True if ordered and equal - SETOGT, // 0 0 1 0 True if ordered and greater than - SETOGE, // 0 0 1 1 True if ordered and greater than or equal - SETOLT, // 0 1 0 0 True if ordered and less than - SETOLE, // 0 1 0 1 True if ordered and less than or equal - SETONE, // 0 1 1 0 True if ordered and operands are unequal - SETO, // 0 1 1 1 True if ordered (no nans) - SETUO, // 1 0 0 0 True if unordered: isnan(X) | isnan(Y) - SETUEQ, // 1 0 0 1 True if unordered or equal - SETUGT, // 1 0 1 0 True if unordered or greater than - SETUGE, // 1 0 1 1 True if unordered, greater than, or equal - SETULT, // 1 1 0 0 True if unordered or less than - SETULE, // 1 1 0 1 True if unordered, less than, or equal - SETUNE, // 1 1 1 0 True if unordered or not equal - SETTRUE, // 1 1 1 1 Always true (always folded) - // Don't care operations: undefined if the input is a nan. - SETFALSE2, // 1 X 0 0 0 Always false (always folded) - SETEQ, // 1 X 0 0 1 True if equal - SETGT, // 1 X 0 1 0 True if greater than - SETGE, // 1 X 0 1 1 True if greater than or equal - SETLT, // 1 X 1 0 0 True if less than - SETLE, // 1 X 1 0 1 True if less than or equal - SETNE, // 1 X 1 1 0 True if not equal - SETTRUE2, // 1 X 1 1 1 Always true (always folded) - - SETCC_INVALID // Marker value. - }; - - /// isSignedIntSetCC - Return true if this is a setcc instruction that - /// performs a signed comparison when used with integer operands. - inline bool isSignedIntSetCC(CondCode Code) { - return Code == SETGT || Code == SETGE || Code == SETLT || Code == SETLE; - } - - /// isUnsignedIntSetCC - Return true if this is a setcc instruction that - /// performs an unsigned comparison when used with integer operands. - inline bool isUnsignedIntSetCC(CondCode Code) { - return Code == SETUGT || Code == SETUGE || Code == SETULT || Code == SETULE; - } - - /// isTrueWhenEqual - Return true if the specified condition returns true if - /// the two operands to the condition are equal. Note that if one of the two - /// operands is a NaN, this value is meaningless. - inline bool isTrueWhenEqual(CondCode Cond) { - return ((int)Cond & 1) != 0; - } - - /// getUnorderedFlavor - This function returns 0 if the condition is always - /// false if an operand is a NaN, 1 if the condition is always true if the - /// operand is a NaN, and 2 if the condition is undefined if the operand is a - /// NaN. - inline unsigned getUnorderedFlavor(CondCode Cond) { - return ((int)Cond >> 3) & 3; - } - - /// getSetCCInverse - Return the operation corresponding to !(X op Y), where - /// 'op' is a valid SetCC operation. - CondCode getSetCCInverse(CondCode Operation, bool isInteger); - - /// getSetCCSwappedOperands - Return the operation corresponding to (Y op X) - /// when given the operation for (X op Y). - CondCode getSetCCSwappedOperands(CondCode Operation); - - /// getSetCCOrOperation - Return the result of a logical OR between different - /// comparisons of identical values: ((X op1 Y) | (X op2 Y)). This - /// function returns SETCC_INVALID if it is not possible to represent the - /// resultant comparison. - CondCode getSetCCOrOperation(CondCode Op1, CondCode Op2, bool isInteger); - - /// getSetCCAndOperation - Return the result of a logical AND between - /// different comparisons of identical values: ((X op1 Y) & (X op2 Y)). This - /// function returns SETCC_INVALID if it is not possible to represent the - /// resultant comparison. - CondCode getSetCCAndOperation(CondCode Op1, CondCode Op2, bool isInteger); - - //===--------------------------------------------------------------------===// - /// CvtCode enum - This enum defines the various converts CONVERT_RNDSAT - /// supports. - enum CvtCode { - CVT_FF, // Float from Float - CVT_FS, // Float from Signed - CVT_FU, // Float from Unsigned - CVT_SF, // Signed from Float - CVT_UF, // Unsigned from Float - CVT_SS, // Signed from Signed - CVT_SU, // Signed from Unsigned - CVT_US, // Unsigned from Signed - CVT_UU, // Unsigned from Unsigned - CVT_INVALID // Marker - Invalid opcode - }; -} // end llvm::ISD namespace - +} // end llvm:ISD namespace //===----------------------------------------------------------------------===// /// SDValue - Unlike LLVM values, Selection DAG nodes may return multiple @@ -835,6 +101,8 @@ public: /// set the SDNode void setNode(SDNode *N) { Node = N; } + inline SDNode *operator->() const { return Node; } + bool operator==(const SDValue &O) const { return Node == O.Node && ResNo == O.ResNo; } @@ -867,6 +135,7 @@ public: inline unsigned getNumOperands() const; inline const SDValue &getOperand(unsigned i) const; inline uint64_t getConstantOperandVal(unsigned i) const; + inline bool isTargetMemoryOpcode() const; inline bool isTargetOpcode() const; inline bool isMachineOpcode() const; inline unsigned getMachineOpcode() const; @@ -907,8 +176,9 @@ template<> struct DenseMapInfo { static bool isEqual(const SDValue &LHS, const SDValue &RHS) { return LHS == RHS; } - static bool isPod() { return true; } }; +template <> struct isPodLike { static const bool value = true; }; + /// simplify_type specializations - Allow casting operators to work directly on /// SDValues as if they were SDNode*'s. @@ -1031,17 +301,21 @@ class SDNode : public FoldingSetNode, public ilist_node { private: /// NodeType - The operation that this node performs. /// - short NodeType; + int16_t 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; + uint16_t OperandsNeedDelete : 1; + + /// HasDebugValue - This tracks whether this node has one or more dbg_value + /// nodes corresponding to it. + uint16_t HasDebugValue : 1; protected: /// SubclassData - 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. - unsigned short SubclassData : 15; + uint16_t SubclassData : 14; private: /// NodeId - Unique id per SDNode in the DAG. @@ -1085,6 +359,13 @@ public: /// \ISD namespace). bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; } + /// isTargetMemoryOpcode - Test if this node has a target-specific + /// memory-referencing opcode (in the \ISD namespace and + /// greater than FIRST_TARGET_MEMORY_OPCODE). + bool isTargetMemoryOpcode() const { + return NodeType >= ISD::FIRST_TARGET_MEMORY_OPCODE; + } + /// isMachineOpcode - Test if this node has a post-isel opcode, directly /// corresponding to a MachineInstr opcode. bool isMachineOpcode() const { return NodeType < 0; } @@ -1097,6 +378,12 @@ public: return ~NodeType; } + /// getHasDebugValue - get this bit. + bool getHasDebugValue() const { return HasDebugValue; } + + /// setHasDebugValue - set this bit. + void setHasDebugValue(bool b) { HasDebugValue = b; } + /// use_empty - Return true if there are no uses of this node. /// bool use_empty() const { return UseList == NULL; } @@ -1104,7 +391,7 @@ public: /// hasOneUse - Return true if there is exactly one use of this node. /// bool hasOneUse() const { - return !use_empty() && next(use_begin()) == use_end(); + return !use_empty() && llvm::next(use_begin()) == use_end(); } /// use_size - Return the number of uses of this node. This method takes @@ -1129,14 +416,16 @@ public: /// use_iterator - This class provides iterator support for SDUse /// operands that use a specific SDNode. class use_iterator - : public forward_iterator { + : public std::iterator { SDUse *Op; explicit use_iterator(SDUse *op) : Op(op) { } friend class SDNode; public: - typedef forward_iterator::reference reference; - typedef forward_iterator::pointer pointer; + typedef std::iterator::reference reference; + typedef std::iterator::pointer pointer; use_iterator(const use_iterator &I) : Op(I.Op) {} use_iterator() : Op(0) {} @@ -1233,7 +522,7 @@ public: SDVTList getVTList() const { SDVTList X = { ValueList, NumValues }; return X; - }; + } /// getFlaggedNode - If this node has a flag operand, return the node /// to which the flag operand points. Otherwise return NULL. @@ -1260,6 +549,15 @@ public: return FoundNode; } + /// getFlaggedUser - If this node has a flag value with a user, return + /// the user (there is at most one). Otherwise return NULL. + SDNode *getFlaggedUser() const { + for (use_iterator UI = use_begin(), UE = use_end(); UI != UE; ++UI) + if (UI.getUse().get().getValueType() == MVT::Flag) + return *UI; + return 0; + } + /// getNumValues - Return the number of values defined/returned by this /// operator. /// @@ -1290,10 +588,56 @@ public: void print_details(raw_ostream &OS, const SelectionDAG *G) const; void print(raw_ostream &OS, const SelectionDAG *G = 0) const; void printr(raw_ostream &OS, const SelectionDAG *G = 0) const; + + /// printrFull - Print a SelectionDAG node and all children down to + /// the leaves. The given SelectionDAG allows target-specific nodes + /// to be printed in human-readable form. Unlike printr, this will + /// print the whole DAG, including children that appear multiple + /// times. + /// + void printrFull(raw_ostream &O, const SelectionDAG *G = 0) const; + + /// printrWithDepth - Print a SelectionDAG node and children up to + /// depth "depth." The given SelectionDAG allows target-specific + /// nodes to be printed in human-readable form. Unlike printr, this + /// will print children that appear multiple times wherever they are + /// used. + /// + void printrWithDepth(raw_ostream &O, const SelectionDAG *G = 0, + unsigned depth = 100) const; + + + /// dump - Dump this node, for debugging. void dump() const; + + /// dumpr - Dump (recursively) this node and its use-def subgraph. void dumpr() const; + + /// dump - Dump this node, for debugging. + /// The given SelectionDAG allows target-specific nodes to be printed + /// in human-readable form. void dump(const SelectionDAG *G) const; + /// dumpr - Dump (recursively) this node and its use-def subgraph. + /// The given SelectionDAG allows target-specific nodes to be printed + /// in human-readable form. + void dumpr(const SelectionDAG *G) const; + + /// dumprFull - printrFull to dbgs(). The given SelectionDAG allows + /// target-specific nodes to be printed in human-readable form. + /// Unlike dumpr, this will print the whole DAG, including children + /// that appear multiple times. + /// + void dumprFull(const SelectionDAG *G = 0) const; + + /// dumprWithDepth - printrWithDepth to dbgs(). The given + /// SelectionDAG allows target-specific nodes to be printed in + /// human-readable form. Unlike dumpr, this will print children + /// that appear multiple times wherever they are used. + /// + void dumprWithDepth(const SelectionDAG *G = 0, unsigned depth = 100) const; + + static bool classof(const SDNode *) { return true; } /// Profile - Gather unique data for the node. @@ -1312,8 +656,8 @@ protected: SDNode(unsigned Opc, const DebugLoc dl, SDVTList VTs, const SDValue *Ops, unsigned NumOps) - : NodeType(Opc), OperandsNeedDelete(true), SubclassData(0), - NodeId(-1), + : NodeType(Opc), OperandsNeedDelete(true), HasDebugValue(false), + SubclassData(0), NodeId(-1), OperandList(NumOps ? new SDUse[NumOps] : 0), ValueList(VTs.VTs), UseList(NULL), NumOperands(NumOps), NumValues(VTs.NumVTs), @@ -1322,14 +666,15 @@ protected: OperandList[i].setUser(this); OperandList[i].setInitial(Ops[i]); } + checkForCycles(this); } /// This constructor adds no operands itself; operands can be /// set later with InitOperands. SDNode(unsigned Opc, const DebugLoc dl, SDVTList VTs) - : NodeType(Opc), OperandsNeedDelete(false), SubclassData(0), - NodeId(-1), OperandList(0), ValueList(VTs.VTs), UseList(NULL), - NumOperands(0), NumValues(VTs.NumVTs), + : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false), + SubclassData(0), 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. @@ -1338,6 +683,7 @@ protected: Ops[0].setInitial(Op0); NumOperands = 1; OperandList = Ops; + checkForCycles(this); } /// InitOperands - Initialize the operands list of this with 2 operands. @@ -1348,6 +694,7 @@ protected: Ops[1].setInitial(Op1); NumOperands = 2; OperandList = Ops; + checkForCycles(this); } /// InitOperands - Initialize the operands list of this with 3 operands. @@ -1361,6 +708,7 @@ protected: Ops[2].setInitial(Op2); NumOperands = 3; OperandList = Ops; + checkForCycles(this); } /// InitOperands - Initialize the operands list of this with 4 operands. @@ -1376,6 +724,7 @@ protected: Ops[3].setInitial(Op3); NumOperands = 4; OperandList = Ops; + checkForCycles(this); } /// InitOperands - Initialize the operands list of this with N operands. @@ -1386,6 +735,7 @@ protected: } NumOperands = N; OperandList = Ops; + checkForCycles(this); } /// DropOperands - Release the operands and set this node to have @@ -1414,6 +764,9 @@ inline uint64_t SDValue::getConstantOperandVal(unsigned i) const { inline bool SDValue::isTargetOpcode() const { return Node->isTargetOpcode(); } +inline bool SDValue::isTargetMemoryOpcode() const { + return Node->isTargetMemoryOpcode(); +} inline bool SDValue::isMachineOpcode() const { return Node->isMachineOpcode(); } @@ -1493,13 +846,12 @@ class HandleSDNode : public SDNode { public: // FIXME: Remove the "noinline" attribute once is // fixed. -#ifdef __GNUC__ +#if __GNUC__==4 && __GNUC_MINOR__==2 && defined(__APPLE__) && !defined(__llvm__) explicit __attribute__((__noinline__)) HandleSDNode(SDValue X) #else explicit HandleSDNode(SDValue X) #endif - : SDNode(ISD::HANDLENODE, DebugLoc::getUnknownLoc(), - getSDVTList(MVT::Other)) { + : SDNode(ISD::HANDLENODE, DebugLoc(), getSDVTList(MVT::Other)) { InitOperands(&Op, X); } ~HandleSDNode(); @@ -1512,43 +864,58 @@ private: // MemoryVT - VT of in-memory value. EVT MemoryVT; - //! SrcValue - Memory location for alias analysis. - const Value *SrcValue; - - //! SVOffset - Memory location offset. Note that base is defined in MemSDNode - int SVOffset; +protected: + /// MMO - Memory reference information. + MachineMemOperand *MMO; public: MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, EVT MemoryVT, - const Value *srcValue, int SVOff, - unsigned alignment, bool isvolatile); + MachineMemOperand *MMO); MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, const SDValue *Ops, - unsigned NumOps, EVT MemoryVT, const Value *srcValue, int SVOff, - unsigned alignment, bool isvolatile); + unsigned NumOps, EVT MemoryVT, MachineMemOperand *MMO); + + bool readMem() const { return MMO->isLoad(); } + bool writeMem() const { return MMO->isStore(); } /// Returns alignment and volatility of the memory access - unsigned getAlignment() const { return (1u << (SubclassData >> 6)) >> 1; } - bool isVolatile() const { return (SubclassData >> 5) & 1; } + unsigned getOriginalAlignment() const { + return MMO->getBaseAlignment(); + } + unsigned getAlignment() const { + return MMO->getAlignment(); + } /// getRawSubclassData - Return the SubclassData value, which contains an - /// encoding of the alignment and volatile information, as well as bits - /// used by subclasses. This function should only be used to compute a - /// FoldingSetNodeID value. + /// encoding of the volatile flag, as well as bits used by subclasses. This + /// function should only be used to compute a FoldingSetNodeID value. unsigned getRawSubclassData() const { return SubclassData; } + // 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; } + /// Returns the SrcValue and offset that describes the location of the access - const Value *getSrcValue() const { return SrcValue; } - int getSrcValueOffset() const { return SVOffset; } + const Value *getSrcValue() const { return MMO->getValue(); } + int64_t getSrcValueOffset() const { return MMO->getOffset(); } /// getMemoryVT - Return the type of the in-memory value. EVT getMemoryVT() const { return MemoryVT; } /// getMemOperand - Return a MachineMemOperand object describing the memory /// reference performed by operation. - MachineMemOperand getMemOperand() const; + MachineMemOperand *getMemOperand() const { return MMO; } + + /// refineAlignment - Update this MemSDNode's MachineMemOperand information + /// to reflect the alignment of NewMMO, if it has a greater alignment. + /// This must only be used when the new alignment applies to all users of + /// this MachineMemOperand. + void refineAlignment(const MachineMemOperand *NewMMO) { + MMO->refineAlignment(NewMMO); + } const SDValue &getChain() const { return getOperand(0); } const SDValue &getBasePtr() const { @@ -1574,9 +941,7 @@ public: N->getOpcode() == ISD::ATOMIC_LOAD_MAX || N->getOpcode() == ISD::ATOMIC_LOAD_UMIN || N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || - N->getOpcode() == ISD::INTRINSIC_W_CHAIN || - N->getOpcode() == ISD::INTRINSIC_VOID || - N->isTargetOpcode(); + N->isTargetMemoryOpcode(); } }; @@ -1596,17 +961,18 @@ public: // Align: alignment of memory AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, SDValue Chain, SDValue Ptr, - SDValue Cmp, SDValue Swp, const Value* SrcVal, - unsigned Align=0) - : MemSDNode(Opc, dl, VTL, MemVT, SrcVal, /*SVOffset=*/0, - Align, /*isVolatile=*/true) { + SDValue Cmp, SDValue Swp, MachineMemOperand *MMO) + : MemSDNode(Opc, dl, VTL, MemVT, MMO) { + assert(readMem() && "Atomic MachineMemOperand is not a load!"); + assert(writeMem() && "Atomic MachineMemOperand is not a store!"); InitOperands(Ops, Chain, Ptr, Cmp, Swp); } AtomicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTL, EVT MemVT, SDValue Chain, SDValue Ptr, - SDValue Val, const Value* SrcVal, unsigned Align=0) - : MemSDNode(Opc, dl, VTL, MemVT, SrcVal, /*SVOffset=*/0, - Align, /*isVolatile=*/true) { + SDValue Val, MachineMemOperand *MMO) + : MemSDNode(Opc, dl, VTL, MemVT, MMO) { + assert(readMem() && "Atomic MachineMemOperand is not a load!"); + assert(writeMem() && "Atomic MachineMemOperand is not a store!"); InitOperands(Ops, Chain, Ptr, Val); } @@ -1636,24 +1002,18 @@ public: } }; -/// MemIntrinsicSDNode - This SDNode is used for target intrinsic that touches -/// memory and need an associated memory operand. -/// +/// MemIntrinsicSDNode - This SDNode is used for target intrinsics that touch +/// memory and need an associated MachineMemOperand. Its opcode may be +/// INTRINSIC_VOID, INTRINSIC_W_CHAIN, or a target-specific opcode with a +/// value not less than FIRST_TARGET_MEMORY_OPCODE. class MemIntrinsicSDNode : public MemSDNode { - bool ReadMem; // Intrinsic reads memory - bool WriteMem; // Intrinsic writes memory public: MemIntrinsicSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, const SDValue *Ops, unsigned NumOps, - EVT MemoryVT, const Value *srcValue, int SVO, - unsigned Align, bool Vol, bool ReadMem, bool WriteMem) - : MemSDNode(Opc, dl, VTs, Ops, NumOps, MemoryVT, srcValue, SVO, Align, Vol), - ReadMem(ReadMem), WriteMem(WriteMem) { + EVT MemoryVT, MachineMemOperand *MMO) + : MemSDNode(Opc, dl, VTs, Ops, NumOps, MemoryVT, MMO) { } - bool readMem() const { return ReadMem; } - bool writeMem() const { return WriteMem; } - // Methods to support isa and dyn_cast static bool classof(const MemIntrinsicSDNode *) { return true; } static bool classof(const SDNode *N) { @@ -1661,7 +1021,7 @@ public: // early a node with a target opcode can be of this class return N->getOpcode() == ISD::INTRINSIC_W_CHAIN || N->getOpcode() == ISD::INTRINSIC_VOID || - N->isTargetOpcode(); + N->isTargetMemoryOpcode(); } }; @@ -1702,7 +1062,12 @@ public: bool isSplat() const { return isSplatMask(Mask, getValueType(0)); } int getSplatIndex() const { assert(isSplat() && "Cannot get splat index for non-splat!"); - return Mask[0]; + EVT VT = getValueType(0); + for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) { + if (Mask[i] != -1) + return Mask[i]; + } + return -1; } static bool isSplatMask(const int *Mask, EVT VT); @@ -1717,7 +1082,7 @@ class ConstantSDNode : public SDNode { friend class SelectionDAG; ConstantSDNode(bool isTarget, const ConstantInt *val, EVT VT) : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, - DebugLoc::getUnknownLoc(), getSDVTList(VT)), Value(val) { + DebugLoc(), getSDVTList(VT)), Value(val) { } public: @@ -1726,6 +1091,7 @@ public: uint64_t getZExtValue() const { return Value->getZExtValue(); } int64_t getSExtValue() const { return Value->getSExtValue(); } + bool isOne() const { return Value->isOne(); } bool isNullValue() const { return Value->isNullValue(); } bool isAllOnesValue() const { return Value->isAllOnesValue(); } @@ -1741,13 +1107,19 @@ class ConstantFPSDNode : public SDNode { friend class SelectionDAG; ConstantFPSDNode(bool isTarget, const ConstantFP *val, EVT VT) : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, - DebugLoc::getUnknownLoc(), getSDVTList(VT)), Value(val) { + DebugLoc(), getSDVTList(VT)), Value(val) { } public: const APFloat& getValueAPF() const { return Value->getValueAPF(); } const ConstantFP *getConstantFPValue() const { return Value; } + /// isZero - Return true if the value is positive or negative zero. + bool isZero() const { return Value->isZero(); } + + /// isNaN - Return true if the value is a NaN. + bool isNaN() const { return Value->isNaN(); } + /// isExactlyValue - We don't rely on operator== working on double values, as /// it returns true for things that are clearly not equal, like -0.0 and 0.0. /// As such, this method can be used to do an exact bit-for-bit comparison of @@ -1768,7 +1140,7 @@ public: } bool isExactlyValue(const APFloat& V) const; - bool isValueValidForType(EVT VT, const APFloat& Val); + static bool isValueValidForType(EVT VT, const APFloat& Val); static bool classof(const ConstantFPSDNode *) { return true; } static bool classof(const SDNode *N) { @@ -1778,7 +1150,7 @@ public: }; class GlobalAddressSDNode : public SDNode { - GlobalValue *TheGlobal; + const GlobalValue *TheGlobal; int64_t Offset; unsigned char TargetFlags; friend class SelectionDAG; @@ -1786,7 +1158,7 @@ class GlobalAddressSDNode : public SDNode { int64_t o, unsigned char TargetFlags); public: - GlobalValue *getGlobal() const { return TheGlobal; } + const 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. @@ -1806,7 +1178,7 @@ class FrameIndexSDNode : public SDNode { friend class SelectionDAG; FrameIndexSDNode(int fi, EVT VT, bool isTarg) : SDNode(isTarg ? ISD::TargetFrameIndex : ISD::FrameIndex, - DebugLoc::getUnknownLoc(), getSDVTList(VT)), FI(fi) { + DebugLoc(), getSDVTList(VT)), FI(fi) { } public: @@ -1825,7 +1197,7 @@ class JumpTableSDNode : public SDNode { friend class SelectionDAG; JumpTableSDNode(int jti, EVT VT, bool isTarg, unsigned char TF) : SDNode(isTarg ? ISD::TargetJumpTable : ISD::JumpTable, - DebugLoc::getUnknownLoc(), getSDVTList(VT)), JTI(jti), TargetFlags(TF) { + DebugLoc(), getSDVTList(VT)), JTI(jti), TargetFlags(TF) { } public: @@ -1841,17 +1213,17 @@ public: class ConstantPoolSDNode : public SDNode { union { - Constant *ConstVal; + const Constant *ConstVal; MachineConstantPoolValue *MachineCPVal; } Val; 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, Constant *c, EVT VT, int o, unsigned Align, - unsigned char TF) + ConstantPoolSDNode(bool isTarget, const Constant *c, EVT VT, int o, + unsigned Align, unsigned char TF) : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, - DebugLoc::getUnknownLoc(), + DebugLoc(), getSDVTList(VT)), Offset(o), Alignment(Align), TargetFlags(TF) { assert((int)Offset >= 0 && "Offset is too large"); Val.ConstVal = c; @@ -1859,7 +1231,7 @@ class ConstantPoolSDNode : public SDNode { ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v, EVT VT, int o, unsigned Align, unsigned char TF) : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, - DebugLoc::getUnknownLoc(), + DebugLoc(), getSDVTList(VT)), Offset(o), Alignment(Align), TargetFlags(TF) { assert((int)Offset >= 0 && "Offset is too large"); Val.MachineCPVal = v; @@ -1872,7 +1244,7 @@ public: return (int)Offset < 0; } - Constant *getConstVal() const { + const Constant *getConstVal() const { assert(!isMachineConstantPoolEntry() && "Wrong constantpool type"); return Val.ConstVal; } @@ -1907,8 +1279,7 @@ class BasicBlockSDNode : public SDNode { /// 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, DebugLoc::getUnknownLoc(), - getSDVTList(MVT::Other)), MBB(mbb) { + : SDNode(ISD::BasicBlock, DebugLoc(), getSDVTList(MVT::Other)), MBB(mbb) { } public: @@ -1934,10 +1305,10 @@ public: /// 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. + /// undefined. isBigEndian describes the endianness of the target. bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, - unsigned MinSplatBits = 0); + unsigned MinSplatBits = 0, bool isBigEndian = false); static inline bool classof(const BuildVectorSDNode *) { return true; } static inline bool classof(const SDNode *N) { @@ -1949,17 +1320,12 @@ public: /// used when the SelectionDAG needs to make a simple reference to something /// in the LLVM IR representation. /// -/// Note that this is not used for carrying alias information; that is done -/// with MemOperandSDNode, which includes a Value which is required to be a -/// pointer, and several other fields specific to memory references. -/// 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, DebugLoc::getUnknownLoc(), - getSDVTList(MVT::Other)), V(v) {} + : SDNode(ISD::SRCVALUE, DebugLoc(), getSDVTList(MVT::Other)), V(v) {} public: /// getValue - return the contained Value. @@ -1970,26 +1336,19 @@ public: return N->getOpcode() == ISD::SRCVALUE; } }; - - -/// MemOperandSDNode - An SDNode that holds a MachineMemOperand. This is -/// used to represent a reference to memory after ISD::LOAD -/// and ISD::STORE have been lowered. -/// -class MemOperandSDNode : public SDNode { + +class MDNodeSDNode : public SDNode { + const MDNode *MD; friend class SelectionDAG; - /// Create a MachineMemOperand node - explicit MemOperandSDNode(const MachineMemOperand &mo) - : SDNode(ISD::MEMOPERAND, DebugLoc::getUnknownLoc(), - getSDVTList(MVT::Other)), MO(mo) {} - + explicit MDNodeSDNode(const MDNode *md) + : SDNode(ISD::MDNODE_SDNODE, DebugLoc(), getSDVTList(MVT::Other)), MD(md) {} public: - /// MO - The contained MachineMemOperand. - const MachineMemOperand MO; - - static bool classof(const MemOperandSDNode *) { return true; } + + const MDNode *getMD() const { return MD; } + + static bool classof(const MDNodeSDNode *) { return true; } static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::MEMOPERAND; + return N->getOpcode() == ISD::MDNODE_SDNODE; } }; @@ -1998,8 +1357,7 @@ class RegisterSDNode : public SDNode { unsigned Reg; friend class SelectionDAG; RegisterSDNode(unsigned reg, EVT VT) - : SDNode(ISD::Register, DebugLoc::getUnknownLoc(), - getSDVTList(VT)), Reg(reg) { + : SDNode(ISD::Register, DebugLoc(), getSDVTList(VT)), Reg(reg) { } public: @@ -2011,44 +1369,40 @@ public: } }; -class DbgStopPointSDNode : public SDNode { - SDUse Chain; - unsigned Line; - unsigned Column; - Value *CU; +class BlockAddressSDNode : public SDNode { + const BlockAddress *BA; + unsigned char TargetFlags; friend class SelectionDAG; - DbgStopPointSDNode(SDValue ch, unsigned l, unsigned c, - Value *cu) - : SDNode(ISD::DBG_STOPPOINT, DebugLoc::getUnknownLoc(), - getSDVTList(MVT::Other)), Line(l), Column(c), CU(cu) { - InitOperands(&Chain, ch); + BlockAddressSDNode(unsigned NodeTy, EVT VT, const BlockAddress *ba, + unsigned char Flags) + : SDNode(NodeTy, DebugLoc(), getSDVTList(VT)), + BA(ba), TargetFlags(Flags) { } public: - unsigned getLine() const { return Line; } - unsigned getColumn() const { return Column; } - Value *getCompileUnit() const { return CU; } + const BlockAddress *getBlockAddress() const { return BA; } + unsigned char getTargetFlags() const { return TargetFlags; } - static bool classof(const DbgStopPointSDNode *) { return true; } + static bool classof(const BlockAddressSDNode *) { return true; } static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::DBG_STOPPOINT; + return N->getOpcode() == ISD::BlockAddress || + N->getOpcode() == ISD::TargetBlockAddress; } }; -class LabelSDNode : public SDNode { +class EHLabelSDNode : public SDNode { SDUse Chain; - unsigned LabelID; + MCSymbol *Label; friend class SelectionDAG; -LabelSDNode(unsigned NodeTy, DebugLoc dl, SDValue ch, unsigned id) - : SDNode(NodeTy, dl, getSDVTList(MVT::Other)), LabelID(id) { + EHLabelSDNode(DebugLoc dl, SDValue ch, MCSymbol *L) + : SDNode(ISD::EH_LABEL, dl, getSDVTList(MVT::Other)), Label(L) { InitOperands(&Chain, ch); } public: - unsigned getLabelID() const { return LabelID; } + MCSymbol *getLabel() const { return Label; } - static bool classof(const LabelSDNode *) { return true; } + static bool classof(const EHLabelSDNode *) { return true; } static bool classof(const SDNode *N) { - return N->getOpcode() == ISD::DBG_LABEL || - N->getOpcode() == ISD::EH_LABEL; + return N->getOpcode() == ISD::EH_LABEL; } }; @@ -2059,8 +1413,7 @@ class ExternalSymbolSDNode : public SDNode { friend class SelectionDAG; ExternalSymbolSDNode(bool isTarget, const char *Sym, unsigned char TF, EVT VT) : SDNode(isTarget ? ISD::TargetExternalSymbol : ISD::ExternalSymbol, - DebugLoc::getUnknownLoc(), - getSDVTList(VT)), Symbol(Sym), TargetFlags(TF) { + DebugLoc(), getSDVTList(VT)), Symbol(Sym), TargetFlags(TF) { } public: @@ -2078,8 +1431,8 @@ class CondCodeSDNode : public SDNode { ISD::CondCode Condition; friend class SelectionDAG; explicit CondCodeSDNode(ISD::CondCode Cond) - : SDNode(ISD::CONDCODE, DebugLoc::getUnknownLoc(), - getSDVTList(MVT::Other)), Condition(Cond) { + : SDNode(ISD::CONDCODE, DebugLoc(), getSDVTList(MVT::Other)), + Condition(Cond) { } public: @@ -2236,8 +1589,8 @@ class VTSDNode : public SDNode { EVT ValueType; friend class SelectionDAG; explicit VTSDNode(EVT VT) - : SDNode(ISD::VALUETYPE, DebugLoc::getUnknownLoc(), - getSDVTList(MVT::Other)), ValueType(VT) { + : SDNode(ISD::VALUETYPE, DebugLoc(), getSDVTList(MVT::Other)), + ValueType(VT) { } public: @@ -2262,9 +1615,8 @@ class LSBaseSDNode : public MemSDNode { public: LSBaseSDNode(ISD::NodeType NodeTy, DebugLoc dl, SDValue *Operands, unsigned numOperands, SDVTList VTs, ISD::MemIndexedMode AM, - EVT VT, const Value *SV, int SVO, unsigned Align, bool Vol) - : MemSDNode(NodeTy, dl, VTs, VT, SV, SVO, Align, Vol) { - assert(Align != 0 && "Loads and stores should have non-zero aligment"); + EVT MemVT, MachineMemOperand *MMO) + : MemSDNode(NodeTy, dl, VTs, MemVT, MMO) { SubclassData |= AM << 2; assert(getAddressingMode() == AM && "MemIndexedMode encoding error!"); InitOperands(Ops, Operands, numOperands); @@ -2300,12 +1652,14 @@ public: class LoadSDNode : public LSBaseSDNode { friend class SelectionDAG; LoadSDNode(SDValue *ChainPtrOff, DebugLoc dl, SDVTList VTs, - ISD::MemIndexedMode AM, ISD::LoadExtType ETy, EVT LVT, - const Value *SV, int O=0, unsigned Align=0, bool Vol=false) + ISD::MemIndexedMode AM, ISD::LoadExtType ETy, EVT MemVT, + MachineMemOperand *MMO) : LSBaseSDNode(ISD::LOAD, dl, ChainPtrOff, 3, - VTs, AM, LVT, SV, O, Align, Vol) { + VTs, AM, MemVT, MMO) { SubclassData |= (unsigned short)ETy; assert(getExtensionType() == ETy && "LoadExtType encoding error!"); + assert(readMem() && "Load MachineMemOperand is not a load!"); + assert(!writeMem() && "Load MachineMemOperand is a store!"); } public: @@ -2329,12 +1683,14 @@ public: class StoreSDNode : public LSBaseSDNode { friend class SelectionDAG; StoreSDNode(SDValue *ChainValuePtrOff, DebugLoc dl, SDVTList VTs, - ISD::MemIndexedMode AM, bool isTrunc, EVT SVT, - const Value *SV, int O=0, unsigned Align=0, bool Vol=false) + ISD::MemIndexedMode AM, bool isTrunc, EVT MemVT, + MachineMemOperand *MMO) : LSBaseSDNode(ISD::STORE, dl, ChainValuePtrOff, 4, - VTs, AM, SVT, SV, O, Align, Vol) { + VTs, AM, MemVT, MMO) { SubclassData |= (unsigned short)isTrunc; assert(isTruncatingStore() == isTrunc && "isTrunc encoding error!"); + assert(!readMem() && "Store MachineMemOperand is a load!"); + assert(writeMem() && "Store MachineMemOperand is not a store!"); } public: @@ -2353,8 +1709,47 @@ public: } }; +/// MachineSDNode - An SDNode that represents everything that will be needed +/// to construct a MachineInstr. These nodes are created during the +/// instruction selection proper phase. +/// +class MachineSDNode : public SDNode { +public: + typedef MachineMemOperand **mmo_iterator; -class SDNodeIterator : public forward_iterator { +private: + friend class SelectionDAG; + MachineSDNode(unsigned Opc, const DebugLoc DL, SDVTList VTs) + : SDNode(Opc, DL, VTs), MemRefs(0), MemRefsEnd(0) {} + + /// LocalOperands - Operands for this instruction, if they fit here. If + /// they don't, this field is unused. + SDUse LocalOperands[4]; + + /// MemRefs - Memory reference descriptions for this instruction. + mmo_iterator MemRefs; + mmo_iterator MemRefsEnd; + +public: + mmo_iterator memoperands_begin() const { return MemRefs; } + mmo_iterator memoperands_end() const { return MemRefsEnd; } + bool memoperands_empty() const { return MemRefsEnd == MemRefs; } + + /// setMemRefs - Assign this MachineSDNodes's memory reference descriptor + /// list. This does not transfer ownership. + void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) { + MemRefs = NewMemRefs; + MemRefsEnd = NewMemRefsEnd; + } + + static bool classof(const MachineSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->isMachineOpcode(); + } +}; + +class SDNodeIterator : public std::iterator { SDNode *Node; unsigned Operand; @@ -2383,6 +1778,11 @@ public: SDNodeIterator operator++(int) { // Postincrement SDNodeIterator tmp = *this; ++*this; return tmp; } + size_t operator-(SDNodeIterator Other) const { + assert(Node == Other.Node && + "Cannot compare iterators of two different nodes!"); + return Operand - Other.Operand; + } static SDNodeIterator begin(SDNode *N) { return SDNodeIterator(N, 0); } static SDNodeIterator end (SDNode *N) { @@ -2486,7 +1886,6 @@ namespace ISD { } } - } // end llvm namespace #endif