diff options
Diffstat (limited to 'capstone/suite/synctools/tablegen/include/llvm/Target')
10 files changed, 4860 insertions, 0 deletions
diff --git a/capstone/suite/synctools/tablegen/include/llvm/Target/GenericOpcodes.td b/capstone/suite/synctools/tablegen/include/llvm/Target/GenericOpcodes.td new file mode 100644 index 000000000..79cc1e4d9 --- /dev/null +++ b/capstone/suite/synctools/tablegen/include/llvm/Target/GenericOpcodes.td @@ -0,0 +1,672 @@ +//===-- GenericOpcodes.td - Opcodes used with GlobalISel ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the generic opcodes used with GlobalISel. +// After instruction selection, these opcodes should not appear. +// +//===----------------------------------------------------------------------===// + +//------------------------------------------------------------------------------ +// Unary ops. +//------------------------------------------------------------------------------ + +class GenericInstruction : StandardPseudoInstruction; + +// Extend the underlying scalar type of an operation, leaving the high bits +// unspecified. +def G_ANYEXT : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src); + let hasSideEffects = 0; +} + +// Sign extend the underlying scalar type of an operation, copying the sign bit +// into the newly-created space. +def G_SEXT : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src); + let hasSideEffects = 0; +} + +// Zero extend the underlying scalar type of an operation, putting zero bits +// into the newly-created space. +def G_ZEXT : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src); + let hasSideEffects = 0; +} + + +// Truncate the underlying scalar type of an operation. This is equivalent to +// G_EXTRACT for scalar types, but acts elementwise on vectors. +def G_TRUNC : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src); + let hasSideEffects = 0; +} + +def G_IMPLICIT_DEF : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins); + let hasSideEffects = 0; +} + +def G_PHI : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins variable_ops); + let hasSideEffects = 0; +} + +def G_FRAME_INDEX : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins unknown:$src2); + let hasSideEffects = 0; +} + +def G_GLOBAL_VALUE : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins unknown:$src); + let hasSideEffects = 0; +} + +def G_INTTOPTR : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src); + let hasSideEffects = 0; +} + +def G_PTRTOINT : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src); + let hasSideEffects = 0; +} + +def G_BITCAST : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src); + let hasSideEffects = 0; +} + +def G_CONSTANT : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins unknown:$imm); + let hasSideEffects = 0; +} + +def G_FCONSTANT : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins unknown:$imm); + let hasSideEffects = 0; +} + +def G_VASTART : GenericInstruction { + let OutOperandList = (outs); + let InOperandList = (ins type0:$list); + let hasSideEffects = 0; + let mayStore = 1; +} + +def G_VAARG : GenericInstruction { + let OutOperandList = (outs type0:$val); + let InOperandList = (ins type1:$list, unknown:$align); + let hasSideEffects = 0; + let mayLoad = 1; + let mayStore = 1; +} + +def G_BSWAP : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src); + let hasSideEffects = 0; +} + +def G_ADDRSPACE_CAST : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src); + let hasSideEffects = 0; +} + +def G_BLOCK_ADDR : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins unknown:$ba); + let hasSideEffects = 0; +} + +//------------------------------------------------------------------------------ +// Binary ops. +//------------------------------------------------------------------------------ + +// Generic addition. +def G_ADD : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// Generic subtraction. +def G_SUB : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 0; +} + +// Generic multiplication. +def G_MUL : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// Generic signed division. +def G_SDIV : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 0; +} + +// Generic unsigned division. +def G_UDIV : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 0; +} + +// Generic signed remainder. +def G_SREM : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 0; +} + +// Generic unsigned remainder. +def G_UREM : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 0; +} + +// Generic bitwise and. +def G_AND : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// Generic bitwise or. +def G_OR : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// Generic bitwise xor. +def G_XOR : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// Generic left-shift. +def G_SHL : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; +} + +// Generic logical right-shift. +def G_LSHR : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; +} + +// Generic arithmetic right-shift. +def G_ASHR : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; +} + +// Generic integer comparison. +def G_ICMP : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2); + let hasSideEffects = 0; +} + +// Generic floating-point comparison. +def G_FCMP : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2); + let hasSideEffects = 0; +} + +// Generic select +def G_SELECT : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$tst, type0:$src1, type0:$src2); + let hasSideEffects = 0; +} + +// Generic pointer offset. +def G_GEP : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type1:$src2); + let hasSideEffects = 0; +} + +def G_PTR_MASK : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src, unknown:$bits); + let hasSideEffects = 0; +} + +//------------------------------------------------------------------------------ +// Overflow ops +//------------------------------------------------------------------------------ + +// Generic unsigned addition consuming and producing a carry flag. +def G_UADDE : GenericInstruction { + let OutOperandList = (outs type0:$dst, type1:$carry_out); + let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in); + let hasSideEffects = 0; +} + +// Generic signed addition producing a carry flag. +def G_SADDO : GenericInstruction { + let OutOperandList = (outs type0:$dst, type1:$carry_out); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// Generic unsigned subtraction consuming and producing a carry flag. +def G_USUBE : GenericInstruction { + let OutOperandList = (outs type0:$dst, type1:$carry_out); + let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in); + let hasSideEffects = 0; +} + +// Generic unsigned subtraction producing a carry flag. +def G_SSUBO : GenericInstruction { + let OutOperandList = (outs type0:$dst, type1:$carry_out); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; +} + +// Generic unsigned multiplication producing a carry flag. +def G_UMULO : GenericInstruction { + let OutOperandList = (outs type0:$dst, type1:$carry_out); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// Generic signed multiplication producing a carry flag. +def G_SMULO : GenericInstruction { + let OutOperandList = (outs type0:$dst, type1:$carry_out); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// Multiply two numbers at twice the incoming bit width (unsigned) and return +// the high half of the result. +def G_UMULH : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// Multiply two numbers at twice the incoming bit width (signed) and return +// the high half of the result. +def G_SMULH : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +//------------------------------------------------------------------------------ +// Floating Point Unary Ops. +//------------------------------------------------------------------------------ + +def G_FNEG : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src); + let hasSideEffects = 0; +} + +def G_FPEXT : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src); + let hasSideEffects = 0; +} + +def G_FPTRUNC : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src); + let hasSideEffects = 0; +} + +def G_FPTOSI : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src); + let hasSideEffects = 0; +} + +def G_FPTOUI : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src); + let hasSideEffects = 0; +} + +def G_SITOFP : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src); + let hasSideEffects = 0; +} + +def G_UITOFP : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src); + let hasSideEffects = 0; +} + +def G_FABS : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src); + let hasSideEffects = 0; +} + +//------------------------------------------------------------------------------ +// Floating Point Binary ops. +//------------------------------------------------------------------------------ + +// Generic FP addition. +def G_FADD : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// Generic FP subtraction. +def G_FSUB : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 0; +} + +// Generic FP multiplication. +def G_FMUL : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; + let isCommutable = 1; +} + +// Generic fused multiply-add instruction. +// Behaves like llvm fma intrinsic ie src1 * src2 + src3 +def G_FMA : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3); + let hasSideEffects = 0; + let isCommutable = 0; +} + +// Generic FP division. +def G_FDIV : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; +} + +// Generic FP remainder. +def G_FREM : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; +} + +// Floating point exponentiation. +def G_FPOW : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1, type0:$src2); + let hasSideEffects = 0; +} + +// Floating point base-e exponential of a value. +def G_FEXP : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1); + let hasSideEffects = 0; +} + +// Floating point base-2 exponential of a value. +def G_FEXP2 : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1); + let hasSideEffects = 0; +} + +// Floating point base-2 logarithm of a value. +def G_FLOG : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1); + let hasSideEffects = 0; +} + +// Floating point base-2 logarithm of a value. +def G_FLOG2 : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src1); + let hasSideEffects = 0; +} + +//------------------------------------------------------------------------------ +// Memory ops +//------------------------------------------------------------------------------ + +// Generic load. Expects a MachineMemOperand in addition to explicit operands. +def G_LOAD : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins ptype1:$addr); + let hasSideEffects = 0; + let mayLoad = 1; +} + +// Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands. +def G_SEXTLOAD : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins ptype1:$addr); + let hasSideEffects = 0; + let mayLoad = 1; +} + +// Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands. +def G_ZEXTLOAD : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins ptype1:$addr); + let hasSideEffects = 0; + let mayLoad = 1; +} + +// Generic store. Expects a MachineMemOperand in addition to explicit operands. +def G_STORE : GenericInstruction { + let OutOperandList = (outs); + let InOperandList = (ins type0:$src, ptype1:$addr); + let hasSideEffects = 0; + let mayStore = 1; +} + +// Generic atomic cmpxchg with internal success check. Expects a +// MachineMemOperand in addition to explicit operands. +def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction { + let OutOperandList = (outs type0:$oldval, type1:$success); + let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval); + let hasSideEffects = 0; + let mayLoad = 1; + let mayStore = 1; +} + +// Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit +// operands. +def G_ATOMIC_CMPXCHG : GenericInstruction { + let OutOperandList = (outs type0:$oldval); + let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval); + let hasSideEffects = 0; + let mayLoad = 1; + let mayStore = 1; +} + +// Generic atomicrmw. Expects a MachineMemOperand in addition to explicit +// operands. +class G_ATOMICRMW_OP : GenericInstruction { + let OutOperandList = (outs type0:$oldval); + let InOperandList = (ins ptype1:$addr, type0:$val); + let hasSideEffects = 0; + let mayLoad = 1; + let mayStore = 1; +} + +def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP; +def G_ATOMICRMW_ADD : G_ATOMICRMW_OP; +def G_ATOMICRMW_SUB : G_ATOMICRMW_OP; +def G_ATOMICRMW_AND : G_ATOMICRMW_OP; +def G_ATOMICRMW_NAND : G_ATOMICRMW_OP; +def G_ATOMICRMW_OR : G_ATOMICRMW_OP; +def G_ATOMICRMW_XOR : G_ATOMICRMW_OP; +def G_ATOMICRMW_MAX : G_ATOMICRMW_OP; +def G_ATOMICRMW_MIN : G_ATOMICRMW_OP; +def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP; +def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP; + +//------------------------------------------------------------------------------ +// Variadic ops +//------------------------------------------------------------------------------ + +// Extract a register of the specified size, starting from the block given by +// index. This will almost certainly be mapped to sub-register COPYs after +// register banks have been selected. +def G_EXTRACT : GenericInstruction { + let OutOperandList = (outs type0:$res); + let InOperandList = (ins type1:$src, unknown:$offset); + let hasSideEffects = 0; +} + +// Extract multiple registers specified size, starting from blocks given by +// indexes. This will almost certainly be mapped to sub-register COPYs after +// register banks have been selected. +def G_UNMERGE_VALUES : GenericInstruction { + let OutOperandList = (outs type0:$dst0, variable_ops); + let InOperandList = (ins type1:$src); + let hasSideEffects = 0; +} + +// Insert a smaller register into a larger one at the specified bit-index. +def G_INSERT : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src, type1:$op, unknown:$offset); + let hasSideEffects = 0; +} + +/// Concatenate multiple registers of the same size into a wider register. +def G_MERGE_VALUES : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src0, variable_ops); + let hasSideEffects = 0; +} + +// Intrinsic without side effects. +def G_INTRINSIC : GenericInstruction { + let OutOperandList = (outs); + let InOperandList = (ins unknown:$intrin, variable_ops); + let hasSideEffects = 0; +} + +// Intrinsic with side effects. +def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction { + let OutOperandList = (outs); + let InOperandList = (ins unknown:$intrin, variable_ops); + let hasSideEffects = 1; + let mayLoad = 1; + let mayStore = 1; +} + +//------------------------------------------------------------------------------ +// Branches. +//------------------------------------------------------------------------------ + +// Generic unconditional branch. +def G_BR : GenericInstruction { + let OutOperandList = (outs); + let InOperandList = (ins unknown:$src1); + let hasSideEffects = 0; + let isBranch = 1; + let isTerminator = 1; + let isBarrier = 1; +} + +// Generic conditional branch. +def G_BRCOND : GenericInstruction { + let OutOperandList = (outs); + let InOperandList = (ins type0:$tst, unknown:$truebb); + let hasSideEffects = 0; + let isBranch = 1; + let isTerminator = 1; +} + +// Generic indirect branch. +def G_BRINDIRECT : GenericInstruction { + let OutOperandList = (outs); + let InOperandList = (ins type0:$src1); + let hasSideEffects = 0; + let isBranch = 1; + let isTerminator = 1; +} + +//------------------------------------------------------------------------------ +// Vector ops +//------------------------------------------------------------------------------ + +// Generic insertelement. +def G_INSERT_VECTOR_ELT : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src, type1:$elt, type2:$idx); + let hasSideEffects = 0; +} + +// Generic extractelement. +def G_EXTRACT_VECTOR_ELT : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src, type2:$idx); + let hasSideEffects = 0; +} + +// Generic shufflevector. +def G_SHUFFLE_VECTOR: GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$v1, type1:$v2, type2:$mask); + let hasSideEffects = 0; +} + +// TODO: Add the other generic opcodes. diff --git a/capstone/suite/synctools/tablegen/include/llvm/Target/GlobalISel/RegisterBank.td b/capstone/suite/synctools/tablegen/include/llvm/Target/GlobalISel/RegisterBank.td new file mode 100644 index 000000000..4dfd139e9 --- /dev/null +++ b/capstone/suite/synctools/tablegen/include/llvm/Target/GlobalISel/RegisterBank.td @@ -0,0 +1,16 @@ +//===- RegisterBank.td - Register bank definitions ---------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +class RegisterBank<string name, list<RegisterClass> classes> { + string Name = name; + list<RegisterClass> RegisterClasses = classes; +} diff --git a/capstone/suite/synctools/tablegen/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/capstone/suite/synctools/tablegen/include/llvm/Target/GlobalISel/SelectionDAGCompat.td new file mode 100644 index 000000000..d487759a4 --- /dev/null +++ b/capstone/suite/synctools/tablegen/include/llvm/Target/GlobalISel/SelectionDAGCompat.td @@ -0,0 +1,131 @@ +//===- TargetGlobalISel.td - Common code for GlobalISel ----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the target-independent interfaces used to support +// SelectionDAG instruction selection patterns (specified in +// TargetSelectionDAG.td) when generating GlobalISel instruction selectors. +// +// This is intended as a compatibility layer, to enable reuse of target +// descriptions written for SelectionDAG without requiring explicit GlobalISel +// support. It will eventually supersede SelectionDAG patterns. +// +//===----------------------------------------------------------------------===// + +// Declare that a generic Instruction is 'equivalent' to an SDNode, that is, +// SelectionDAG patterns involving the SDNode can be transformed to match the +// Instruction instead. +class GINodeEquiv<Instruction i, SDNode node> { + Instruction I = i; + SDNode Node = node; + + // SelectionDAG has separate nodes for atomic and non-atomic memory operations + // (ISD::LOAD, ISD::ATOMIC_LOAD, ISD::STORE, ISD::ATOMIC_STORE) but GlobalISel + // stores this information in the MachineMemoryOperand. + bit CheckMMOIsNonAtomic = 0; + + // SelectionDAG has one node for all loads and uses predicates to + // differentiate them. GlobalISel on the other hand uses separate opcodes. + // When this is true, the resulting opcode is G_LOAD/G_SEXTLOAD/G_ZEXTLOAD + // depending on the predicates on the node. + Instruction IfSignExtend = ?; + Instruction IfZeroExtend = ?; +} + +// These are defined in the same order as the G_* instructions. +def : GINodeEquiv<G_ANYEXT, anyext>; +def : GINodeEquiv<G_SEXT, sext>; +def : GINodeEquiv<G_ZEXT, zext>; +def : GINodeEquiv<G_TRUNC, trunc>; +def : GINodeEquiv<G_BITCAST, bitconvert>; +// G_INTTOPTR - SelectionDAG has no equivalent. +// G_PTRTOINT - SelectionDAG has no equivalent. +def : GINodeEquiv<G_CONSTANT, imm>; +def : GINodeEquiv<G_FCONSTANT, fpimm>; +def : GINodeEquiv<G_ADD, add>; +def : GINodeEquiv<G_SUB, sub>; +def : GINodeEquiv<G_MUL, mul>; +def : GINodeEquiv<G_SDIV, sdiv>; +def : GINodeEquiv<G_UDIV, udiv>; +def : GINodeEquiv<G_SREM, srem>; +def : GINodeEquiv<G_UREM, urem>; +def : GINodeEquiv<G_AND, and>; +def : GINodeEquiv<G_OR, or>; +def : GINodeEquiv<G_XOR, xor>; +def : GINodeEquiv<G_SHL, shl>; +def : GINodeEquiv<G_LSHR, srl>; +def : GINodeEquiv<G_ASHR, sra>; +def : GINodeEquiv<G_SELECT, select>; +def : GINodeEquiv<G_FNEG, fneg>; +def : GINodeEquiv<G_FPEXT, fpextend>; +def : GINodeEquiv<G_FPTRUNC, fpround>; +def : GINodeEquiv<G_FPTOSI, fp_to_sint>; +def : GINodeEquiv<G_FPTOUI, fp_to_uint>; +def : GINodeEquiv<G_SITOFP, sint_to_fp>; +def : GINodeEquiv<G_UITOFP, uint_to_fp>; +def : GINodeEquiv<G_FADD, fadd>; +def : GINodeEquiv<G_FSUB, fsub>; +def : GINodeEquiv<G_FMA, fma>; +def : GINodeEquiv<G_FMUL, fmul>; +def : GINodeEquiv<G_FDIV, fdiv>; +def : GINodeEquiv<G_FREM, frem>; +def : GINodeEquiv<G_FPOW, fpow>; +def : GINodeEquiv<G_FEXP2, fexp2>; +def : GINodeEquiv<G_FLOG2, flog2>; +def : GINodeEquiv<G_INTRINSIC, intrinsic_wo_chain>; +// ISD::INTRINSIC_VOID can also be handled with G_INTRINSIC_W_SIDE_EFFECTS. +def : GINodeEquiv<G_INTRINSIC_W_SIDE_EFFECTS, intrinsic_void>; +def : GINodeEquiv<G_INTRINSIC_W_SIDE_EFFECTS, intrinsic_w_chain>; +def : GINodeEquiv<G_BR, br>; +def : GINodeEquiv<G_BSWAP, bswap>; + +// Broadly speaking G_LOAD is equivalent to ISD::LOAD but there are some +// complications that tablegen must take care of. For example, Predicates such +// as isSignExtLoad require that this is not a perfect 1:1 mapping since a +// sign-extending load is (G_SEXTLOAD x) in GlobalISel. Additionally, +// G_LOAD handles both atomic and non-atomic loads where as SelectionDAG had +// separate nodes for them. This GINodeEquiv maps the non-atomic loads to +// G_LOAD with a non-atomic MachineMemOperand. +def : GINodeEquiv<G_LOAD, ld> { + let CheckMMOIsNonAtomic = 1; + let IfSignExtend = G_SEXTLOAD; + let IfZeroExtend = G_ZEXTLOAD; +} +// Broadly speaking G_STORE is equivalent to ISD::STORE but there are some +// complications that tablegen must take care of. For example, predicates such +// as isTruncStore require that this is not a perfect 1:1 mapping since a +// truncating store is (G_STORE (G_TRUNCATE x)) in GlobalISel. Additionally, +// G_STORE handles both atomic and non-atomic stores where as SelectionDAG had +// separate nodes for them. This GINodeEquiv maps the non-atomic stores to +// G_STORE with a non-atomic MachineMemOperand. +def : GINodeEquiv<G_STORE, st> { let CheckMMOIsNonAtomic = 1; } + +def : GINodeEquiv<G_ATOMIC_CMPXCHG, atomic_cmp_swap>; +def : GINodeEquiv<G_ATOMICRMW_XCHG, atomic_swap>; +def : GINodeEquiv<G_ATOMICRMW_ADD, atomic_load_add>; +def : GINodeEquiv<G_ATOMICRMW_SUB, atomic_load_sub>; +def : GINodeEquiv<G_ATOMICRMW_AND, atomic_load_and>; +def : GINodeEquiv<G_ATOMICRMW_NAND, atomic_load_nand>; +def : GINodeEquiv<G_ATOMICRMW_OR, atomic_load_or>; +def : GINodeEquiv<G_ATOMICRMW_XOR, atomic_load_xor>; +def : GINodeEquiv<G_ATOMICRMW_MIN, atomic_load_min>; +def : GINodeEquiv<G_ATOMICRMW_MAX, atomic_load_max>; +def : GINodeEquiv<G_ATOMICRMW_UMIN, atomic_load_umin>; +def : GINodeEquiv<G_ATOMICRMW_UMAX, atomic_load_umax>; + +// Specifies the GlobalISel equivalents for SelectionDAG's ComplexPattern. +// Should be used on defs that subclass GIComplexOperandMatcher<>. +class GIComplexPatternEquiv<ComplexPattern seldag> { + ComplexPattern SelDAGEquivalent = seldag; +} + +// Specifies the GlobalISel equivalents for SelectionDAG's SDNodeXForm. +// Should be used on defs that subclass GICustomOperandRenderer<>. +class GISDNodeXFormEquiv<SDNodeXForm seldag> { + SDNodeXForm SelDAGEquivalent = seldag; +} diff --git a/capstone/suite/synctools/tablegen/include/llvm/Target/GlobalISel/Target.td b/capstone/suite/synctools/tablegen/include/llvm/Target/GlobalISel/Target.td new file mode 100644 index 000000000..6740f404a --- /dev/null +++ b/capstone/suite/synctools/tablegen/include/llvm/Target/GlobalISel/Target.td @@ -0,0 +1,61 @@ +//===- Target.td - Define GlobalISel rules -----------------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the target-independent interfaces used to support +// SelectionDAG instruction selection patterns (specified in +// TargetSelectionDAG.td) when generating GlobalISel instruction selectors. +// +// This is intended as a compatibility layer, to enable reuse of target +// descriptions written for SelectionDAG without requiring explicit GlobalISel +// support. It will eventually supersede SelectionDAG patterns. +// +//===----------------------------------------------------------------------===// + +// Definitions that inherit from LLT define types that will be used in the +// GlobalISel matcher. +class LLT; + +def s32 : LLT; +def s64 : LLT; + +// Defines a matcher for complex operands. This is analogous to ComplexPattern +// from SelectionDAG. +// +// Definitions that inherit from this may also inherit from +// GIComplexPatternEquiv to enable the import of SelectionDAG patterns involving +// those ComplexPatterns. +class GIComplexOperandMatcher<LLT type, string matcherfn> { + // The expected type of the root of the match. + // + // TODO: We should probably support, any-type, any-scalar, and multiple types + // in the future. + LLT Type = type; + + // The function that determines whether the operand matches. It should be of + // the form: + // bool select(const MatchOperand &Root, MatchOperand &Result1) + // and should have the same number of ResultX arguments as the number of + // result operands. It must return true on successful match and false + // otherwise. If it returns true, then all the ResultX arguments must be + // overwritten. + string MatcherFn = matcherfn; +} + +// Defines a custom renderer. This is analogous to SDNodeXForm from +// SelectionDAG. Unlike SDNodeXForm, this matches a MachineInstr and +// renders directly to the result instruction without an intermediate node. +// +// Definitions that inherit from this may also inherit from GISDNodeXFormEquiv +// to enable the import of SelectionDAG patterns involving those SDNodeXForms. +class GICustomOperandRenderer<string rendererfn> { + // The function renders the operand(s) of the matched instruction to + // the specified instruction. It should be of the form: + // void render(MachineInstrBuilder &MIB, const MachineInstr &MI) + string RendererFn = rendererfn; +} diff --git a/capstone/suite/synctools/tablegen/include/llvm/Target/Target.td b/capstone/suite/synctools/tablegen/include/llvm/Target/Target.td new file mode 100644 index 000000000..b746505d2 --- /dev/null +++ b/capstone/suite/synctools/tablegen/include/llvm/Target/Target.td @@ -0,0 +1,1556 @@ +//===- Target.td - Target Independent TableGen interface ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the target-independent interfaces which should be +// implemented by each target which is using a TableGen based code generator. +// +//===----------------------------------------------------------------------===// + +// Include all information about LLVM intrinsics. +include "llvm/IR/Intrinsics.td" + +//===----------------------------------------------------------------------===// +// Register file description - These classes are used to fill in the target +// description classes. + +class RegisterClass; // Forward def + +class HwMode<string FS> { + // A string representing subtarget features that turn on this HW mode. + // For example, "+feat1,-feat2" will indicate that the mode is active + // when "feat1" is enabled and "feat2" is disabled at the same time. + // Any other features are not checked. + // When multiple modes are used, they should be mutually exclusive, + // otherwise the results are unpredictable. + string Features = FS; +} + +// A special mode recognized by tablegen. This mode is considered active +// when no other mode is active. For targets that do not use specific hw +// modes, this is the only mode. +def DefaultMode : HwMode<"">; + +// A class used to associate objects with HW modes. It is only intended to +// be used as a base class, where the derived class should contain a member +// "Objects", which is a list of the same length as the list of modes. +// The n-th element on the Objects list will be associated with the n-th +// element on the Modes list. +class HwModeSelect<list<HwMode> Ms> { + list<HwMode> Modes = Ms; +} + +// A common class that implements a counterpart of ValueType, which is +// dependent on a HW mode. This class inherits from ValueType itself, +// which makes it possible to use objects of this class where ValueType +// objects could be used. This is specifically applicable to selection +// patterns. +class ValueTypeByHwMode<list<HwMode> Ms, list<ValueType> Ts> + : HwModeSelect<Ms>, ValueType<0, 0> { + // The length of this list must be the same as the length of Ms. + list<ValueType> Objects = Ts; +} + +// A class representing the register size, spill size and spill alignment +// in bits of a register. +class RegInfo<int RS, int SS, int SA> { + int RegSize = RS; // Register size in bits. + int SpillSize = SS; // Spill slot size in bits. + int SpillAlignment = SA; // Spill slot alignment in bits. +} + +// The register size/alignment information, parameterized by a HW mode. +class RegInfoByHwMode<list<HwMode> Ms = [], list<RegInfo> Ts = []> + : HwModeSelect<Ms> { + // The length of this list must be the same as the length of Ms. + list<RegInfo> Objects = Ts; +} + +// SubRegIndex - Use instances of SubRegIndex to identify subregisters. +class SubRegIndex<int size, int offset = 0> { + string Namespace = ""; + + // Size - Size (in bits) of the sub-registers represented by this index. + int Size = size; + + // Offset - Offset of the first bit that is part of this sub-register index. + // Set it to -1 if the same index is used to represent sub-registers that can + // be at different offsets (for example when using an index to access an + // element in a register tuple). + int Offset = offset; + + // ComposedOf - A list of two SubRegIndex instances, [A, B]. + // This indicates that this SubRegIndex is the result of composing A and B. + // See ComposedSubRegIndex. + list<SubRegIndex> ComposedOf = []; + + // CoveringSubRegIndices - A list of two or more sub-register indexes that + // cover this sub-register. + // + // This field should normally be left blank as TableGen can infer it. + // + // TableGen automatically detects sub-registers that straddle the registers + // in the SubRegs field of a Register definition. For example: + // + // Q0 = dsub_0 -> D0, dsub_1 -> D1 + // Q1 = dsub_0 -> D2, dsub_1 -> D3 + // D1_D2 = dsub_0 -> D1, dsub_1 -> D2 + // QQ0 = qsub_0 -> Q0, qsub_1 -> Q1 + // + // TableGen will infer that D1_D2 is a sub-register of QQ0. It will be given + // the synthetic index dsub_1_dsub_2 unless some SubRegIndex is defined with + // CoveringSubRegIndices = [dsub_1, dsub_2]. + list<SubRegIndex> CoveringSubRegIndices = []; +} + +// ComposedSubRegIndex - A sub-register that is the result of composing A and B. +// Offset is set to the sum of A and B's Offsets. Size is set to B's Size. +class ComposedSubRegIndex<SubRegIndex A, SubRegIndex B> + : SubRegIndex<B.Size, !if(!eq(A.Offset, -1), -1, + !if(!eq(B.Offset, -1), -1, + !add(A.Offset, B.Offset)))> { + // See SubRegIndex. + let ComposedOf = [A, B]; +} + +// RegAltNameIndex - The alternate name set to use for register operands of +// this register class when printing. +class RegAltNameIndex { + string Namespace = ""; +} +def NoRegAltName : RegAltNameIndex; + +// Register - You should define one instance of this class for each register +// in the target machine. String n will become the "name" of the register. +class Register<string n, list<string> altNames = []> { + string Namespace = ""; + string AsmName = n; + list<string> AltNames = altNames; + + // Aliases - A list of registers that this register overlaps with. A read or + // modification of this register can potentially read or modify the aliased + // registers. + list<Register> Aliases = []; + + // SubRegs - A list of registers that are parts of this register. Note these + // are "immediate" sub-registers and the registers within the list do not + // themselves overlap. e.g. For X86, EAX's SubRegs list contains only [AX], + // not [AX, AH, AL]. + list<Register> SubRegs = []; + + // SubRegIndices - For each register in SubRegs, specify the SubRegIndex used + // to address it. Sub-sub-register indices are automatically inherited from + // SubRegs. + list<SubRegIndex> SubRegIndices = []; + + // RegAltNameIndices - The alternate name indices which are valid for this + // register. + list<RegAltNameIndex> RegAltNameIndices = []; + + // DwarfNumbers - Numbers used internally by gcc/gdb to identify the register. + // These values can be determined by locating the <target>.h file in the + // directory llvmgcc/gcc/config/<target>/ and looking for REGISTER_NAMES. The + // order of these names correspond to the enumeration used by gcc. A value of + // -1 indicates that the gcc number is undefined and -2 that register number + // is invalid for this mode/flavour. + list<int> DwarfNumbers = []; + + // CostPerUse - Additional cost of instructions using this register compared + // to other registers in its class. The register allocator will try to + // minimize the number of instructions using a register with a CostPerUse. + // This is used by the x86-64 and ARM Thumb targets where some registers + // require larger instruction encodings. + int CostPerUse = 0; + + // CoveredBySubRegs - When this bit is set, the value of this register is + // completely determined by the value of its sub-registers. For example, the + // x86 register AX is covered by its sub-registers AL and AH, but EAX is not + // covered by its sub-register AX. + bit CoveredBySubRegs = 0; + + // HWEncoding - The target specific hardware encoding for this register. + bits<16> HWEncoding = 0; + + bit isArtificial = 0; +} + +// RegisterWithSubRegs - This can be used to define instances of Register which +// need to specify sub-registers. +// List "subregs" specifies which registers are sub-registers to this one. This +// is used to populate the SubRegs and AliasSet fields of TargetRegisterDesc. +// This allows the code generator to be careful not to put two values with +// overlapping live ranges into registers which alias. +class RegisterWithSubRegs<string n, list<Register> subregs> : Register<n> { + let SubRegs = subregs; +} + +// DAGOperand - An empty base class that unifies RegisterClass's and other forms +// of Operand's that are legal as type qualifiers in DAG patterns. This should +// only ever be used for defining multiclasses that are polymorphic over both +// RegisterClass's and other Operand's. +class DAGOperand { + string OperandNamespace = "MCOI"; + string DecoderMethod = ""; +} + +// RegisterClass - Now that all of the registers are defined, and aliases +// between registers are defined, specify which registers belong to which +// register classes. This also defines the default allocation order of +// registers by register allocators. +// +class RegisterClass<string namespace, list<ValueType> regTypes, int alignment, + dag regList, RegAltNameIndex idx = NoRegAltName> + : DAGOperand { + string Namespace = namespace; + + // The register size/alignment information, parameterized by a HW mode. + RegInfoByHwMode RegInfos; + + // RegType - Specify the list ValueType of the registers in this register + // class. Note that all registers in a register class must have the same + // ValueTypes. This is a list because some targets permit storing different + // types in same register, for example vector values with 128-bit total size, + // but different count/size of items, like SSE on x86. + // + list<ValueType> RegTypes = regTypes; + + // Size - Specify the spill size in bits of the registers. A default value of + // zero lets tablgen pick an appropriate size. + int Size = 0; + + // Alignment - Specify the alignment required of the registers when they are + // stored or loaded to memory. + // + int Alignment = alignment; + + // CopyCost - This value is used to specify the cost of copying a value + // between two registers in this register class. The default value is one + // meaning it takes a single instruction to perform the copying. A negative + // value means copying is extremely expensive or impossible. + int CopyCost = 1; + + // MemberList - Specify which registers are in this class. If the + // allocation_order_* method are not specified, this also defines the order of + // allocation used by the register allocator. + // + dag MemberList = regList; + + // AltNameIndex - The alternate register name to use when printing operands + // of this register class. Every register in the register class must have + // a valid alternate name for the given index. + RegAltNameIndex altNameIndex = idx; + + // isAllocatable - Specify that the register class can be used for virtual + // registers and register allocation. Some register classes are only used to + // model instruction operand constraints, and should have isAllocatable = 0. + bit isAllocatable = 1; + + // AltOrders - List of alternative allocation orders. The default order is + // MemberList itself, and that is good enough for most targets since the + // register allocators automatically remove reserved registers and move + // callee-saved registers to the end. + list<dag> AltOrders = []; + + // AltOrderSelect - The body of a function that selects the allocation order + // to use in a given machine function. The code will be inserted in a + // function like this: + // + // static inline unsigned f(const MachineFunction &MF) { ... } + // + // The function should return 0 to select the default order defined by + // MemberList, 1 to select the first AltOrders entry and so on. + code AltOrderSelect = [{}]; + + // Specify allocation priority for register allocators using a greedy + // heuristic. Classes with higher priority values are assigned first. This is + // useful as it is sometimes beneficial to assign registers to highly + // constrained classes first. The value has to be in the range [0,63]. + int AllocationPriority = 0; + + // The diagnostic type to present when referencing this operand in a match + // failure error message. If this is empty, the default Match_InvalidOperand + // diagnostic type will be used. If this is "<name>", a Match_<name> enum + // value will be generated and used for this operand type. The target + // assembly parser is responsible for converting this into a user-facing + // diagnostic message. + string DiagnosticType = ""; + + // A diagnostic message to emit when an invalid value is provided for this + // register class when it is being used an an assembly operand. If this is + // non-empty, an anonymous diagnostic type enum value will be generated, and + // the assembly matcher will provide a function to map from diagnostic types + // to message strings. + string DiagnosticString = ""; +} + +// The memberList in a RegisterClass is a dag of set operations. TableGen +// evaluates these set operations and expand them into register lists. These +// are the most common operation, see test/TableGen/SetTheory.td for more +// examples of what is possible: +// +// (add R0, R1, R2) - Set Union. Each argument can be an individual register, a +// register class, or a sub-expression. This is also the way to simply list +// registers. +// +// (sub GPR, SP) - Set difference. Subtract the last arguments from the first. +// +// (and GPR, CSR) - Set intersection. All registers from the first set that are +// also in the second set. +// +// (sequence "R%u", 0, 15) -> [R0, R1, ..., R15]. Generate a sequence of +// numbered registers. Takes an optional 4th operand which is a stride to use +// when generating the sequence. +// +// (shl GPR, 4) - Remove the first N elements. +// +// (trunc GPR, 4) - Truncate after the first N elements. +// +// (rotl GPR, 1) - Rotate N places to the left. +// +// (rotr GPR, 1) - Rotate N places to the right. +// +// (decimate GPR, 2) - Pick every N'th element, starting with the first. +// +// (interleave A, B, ...) - Interleave the elements from each argument list. +// +// All of these operators work on ordered sets, not lists. That means +// duplicates are removed from sub-expressions. + +// Set operators. The rest is defined in TargetSelectionDAG.td. +def sequence; +def decimate; +def interleave; + +// RegisterTuples - Automatically generate super-registers by forming tuples of +// sub-registers. This is useful for modeling register sequence constraints +// with pseudo-registers that are larger than the architectural registers. +// +// The sub-register lists are zipped together: +// +// def EvenOdd : RegisterTuples<[sube, subo], [(add R0, R2), (add R1, R3)]>; +// +// Generates the same registers as: +// +// let SubRegIndices = [sube, subo] in { +// def R0_R1 : RegisterWithSubRegs<"", [R0, R1]>; +// def R2_R3 : RegisterWithSubRegs<"", [R2, R3]>; +// } +// +// The generated pseudo-registers inherit super-classes and fields from their +// first sub-register. Most fields from the Register class are inferred, and +// the AsmName and Dwarf numbers are cleared. +// +// RegisterTuples instances can be used in other set operations to form +// register classes and so on. This is the only way of using the generated +// registers. +class RegisterTuples<list<SubRegIndex> Indices, list<dag> Regs> { + // SubRegs - N lists of registers to be zipped up. Super-registers are + // synthesized from the first element of each SubRegs list, the second + // element and so on. + list<dag> SubRegs = Regs; + + // SubRegIndices - N SubRegIndex instances. This provides the names of the + // sub-registers in the synthesized super-registers. + list<SubRegIndex> SubRegIndices = Indices; +} + + +//===----------------------------------------------------------------------===// +// DwarfRegNum - This class provides a mapping of the llvm register enumeration +// to the register numbering used by gcc and gdb. These values are used by a +// debug information writer to describe where values may be located during +// execution. +class DwarfRegNum<list<int> Numbers> { + // DwarfNumbers - Numbers used internally by gcc/gdb to identify the register. + // These values can be determined by locating the <target>.h file in the + // directory llvmgcc/gcc/config/<target>/ and looking for REGISTER_NAMES. The + // order of these names correspond to the enumeration used by gcc. A value of + // -1 indicates that the gcc number is undefined and -2 that register number + // is invalid for this mode/flavour. + list<int> DwarfNumbers = Numbers; +} + +// DwarfRegAlias - This class declares that a given register uses the same dwarf +// numbers as another one. This is useful for making it clear that the two +// registers do have the same number. It also lets us build a mapping +// from dwarf register number to llvm register. +class DwarfRegAlias<Register reg> { + Register DwarfAlias = reg; +} + +//===----------------------------------------------------------------------===// +// Pull in the common support for MCPredicate (portable scheduling predicates). +// +include "llvm/Target/TargetInstrPredicate.td" + +//===----------------------------------------------------------------------===// +// Pull in the common support for scheduling +// +include "llvm/Target/TargetSchedule.td" + +class Predicate; // Forward def + +//===----------------------------------------------------------------------===// +// Instruction set description - These classes correspond to the C++ classes in +// the Target/TargetInstrInfo.h file. +// +class Instruction { + string Namespace = ""; + + dag OutOperandList; // An dag containing the MI def operand list. + dag InOperandList; // An dag containing the MI use operand list. + string AsmString = ""; // The .s format to print the instruction with. + + // Pattern - Set to the DAG pattern for this instruction, if we know of one, + // otherwise, uninitialized. + list<dag> Pattern; + + // The follow state will eventually be inferred automatically from the + // instruction pattern. + + list<Register> Uses = []; // Default to using no non-operand registers + list<Register> Defs = []; // Default to modifying no non-operand registers + + // Predicates - List of predicates which will be turned into isel matching + // code. + list<Predicate> Predicates = []; + + // Size - Size of encoded instruction, or zero if the size cannot be determined + // from the opcode. + int Size = 0; + + // DecoderNamespace - The "namespace" in which this instruction exists, on + // targets like ARM which multiple ISA namespaces exist. + string DecoderNamespace = ""; + + // Code size, for instruction selection. + // FIXME: What does this actually mean? + int CodeSize = 0; + + // Added complexity passed onto matching pattern. + int AddedComplexity = 0; + + // These bits capture information about the high-level semantics of the + // instruction. + bit isReturn = 0; // Is this instruction a return instruction? + bit isBranch = 0; // Is this instruction a branch instruction? + bit isIndirectBranch = 0; // Is this instruction an indirect branch? + bit isCompare = 0; // Is this instruction a comparison instruction? + bit isMoveImm = 0; // Is this instruction a move immediate instruction? + bit isMoveReg = 0; // Is this instruction a move register instruction? + bit isBitcast = 0; // Is this instruction a bitcast instruction? + bit isSelect = 0; // Is this instruction a select instruction? + bit isBarrier = 0; // Can control flow fall through this instruction? + bit isCall = 0; // Is this instruction a call instruction? + bit isAdd = 0; // Is this instruction an add instruction? + bit isTrap = 0; // Is this instruction a trap instruction? + bit canFoldAsLoad = 0; // Can this be folded as a simple memory operand? + bit mayLoad = ?; // Is it possible for this inst to read memory? + bit mayStore = ?; // Is it possible for this inst to write memory? + bit isConvertibleToThreeAddress = 0; // Can this 2-addr instruction promote? + bit isCommutable = 0; // Is this 3 operand instruction commutable? + bit isTerminator = 0; // Is this part of the terminator for a basic block? + bit isReMaterializable = 0; // Is this instruction re-materializable? + bit isPredicable = 0; // Is this instruction predicable? + bit hasDelaySlot = 0; // Does this instruction have an delay slot? + bit usesCustomInserter = 0; // Pseudo instr needing special help. + bit hasPostISelHook = 0; // To be *adjusted* after isel by target hook. + bit hasCtrlDep = 0; // Does this instruction r/w ctrl-flow chains? + bit isNotDuplicable = 0; // Is it unsafe to duplicate this instruction? + bit isConvergent = 0; // Is this instruction convergent? + bit isAsCheapAsAMove = 0; // As cheap (or cheaper) than a move instruction. + bit hasExtraSrcRegAllocReq = 0; // Sources have special regalloc requirement? + bit hasExtraDefRegAllocReq = 0; // Defs have special regalloc requirement? + bit isRegSequence = 0; // Is this instruction a kind of reg sequence? + // If so, make sure to override + // TargetInstrInfo::getRegSequenceLikeInputs. + bit isPseudo = 0; // Is this instruction a pseudo-instruction? + // If so, won't have encoding information for + // the [MC]CodeEmitter stuff. + bit isExtractSubreg = 0; // Is this instruction a kind of extract subreg? + // If so, make sure to override + // TargetInstrInfo::getExtractSubregLikeInputs. + bit isInsertSubreg = 0; // Is this instruction a kind of insert subreg? + // If so, make sure to override + // TargetInstrInfo::getInsertSubregLikeInputs. + + // Does the instruction have side effects that are not captured by any + // operands of the instruction or other flags? + bit hasSideEffects = ?; + + // Is this instruction a "real" instruction (with a distinct machine + // encoding), or is it a pseudo instruction used for codegen modeling + // purposes. + // FIXME: For now this is distinct from isPseudo, above, as code-gen-only + // instructions can (and often do) still have encoding information + // associated with them. Once we've migrated all of them over to true + // pseudo-instructions that are lowered to real instructions prior to + // the printer/emitter, we can remove this attribute and just use isPseudo. + // + // The intended use is: + // isPseudo: Does not have encoding information and should be expanded, + // at the latest, during lowering to MCInst. + // + // isCodeGenOnly: Does have encoding information and can go through to the + // CodeEmitter unchanged, but duplicates a canonical instruction + // definition's encoding and should be ignored when constructing the + // assembler match tables. + bit isCodeGenOnly = 0; + + // Is this instruction a pseudo instruction for use by the assembler parser. + bit isAsmParserOnly = 0; + + // This instruction is not expected to be queried for scheduling latencies + // and therefore needs no scheduling information even for a complete + // scheduling model. + bit hasNoSchedulingInfo = 0; + + InstrItinClass Itinerary = NoItinerary;// Execution steps used for scheduling. + + // Scheduling information from TargetSchedule.td. + list<SchedReadWrite> SchedRW; + + string Constraints = ""; // OperandConstraint, e.g. $src = $dst. + + /// DisableEncoding - List of operand names (e.g. "$op1,$op2") that should not + /// be encoded into the output machineinstr. + string DisableEncoding = ""; + + string PostEncoderMethod = ""; + string DecoderMethod = ""; + + // Is the instruction decoder method able to completely determine if the + // given instruction is valid or not. If the TableGen definition of the + // instruction specifies bitpattern A??B where A and B are static bits, the + // hasCompleteDecoder flag says whether the decoder method fully handles the + // ?? space, i.e. if it is a final arbiter for the instruction validity. + // If not then the decoder attempts to continue decoding when the decoder + // method fails. + // + // This allows to handle situations where the encoding is not fully + // orthogonal. Example: + // * InstA with bitpattern 0b0000????, + // * InstB with bitpattern 0b000000?? but the associated decoder method + // DecodeInstB() returns Fail when ?? is 0b00 or 0b11. + // + // The decoder tries to decode a bitpattern that matches both InstA and + // InstB bitpatterns first as InstB (because it is the most specific + // encoding). In the default case (hasCompleteDecoder = 1), when + // DecodeInstB() returns Fail the bitpattern gets rejected. By setting + // hasCompleteDecoder = 0 in InstB, the decoder is informed that + // DecodeInstB() is not able to determine if all possible values of ?? are + // valid or not. If DecodeInstB() returns Fail the decoder will attempt to + // decode the bitpattern as InstA too. + bit hasCompleteDecoder = 1; + + /// Target-specific flags. This becomes the TSFlags field in TargetInstrDesc. + bits<64> TSFlags = 0; + + ///@name Assembler Parser Support + ///@{ + + string AsmMatchConverter = ""; + + /// TwoOperandAliasConstraint - Enable TableGen to auto-generate a + /// two-operand matcher inst-alias for a three operand instruction. + /// For example, the arm instruction "add r3, r3, r5" can be written + /// as "add r3, r5". The constraint is of the same form as a tied-operand + /// constraint. For example, "$Rn = $Rd". + string TwoOperandAliasConstraint = ""; + + /// Assembler variant name to use for this instruction. If specified then + /// instruction will be presented only in MatchTable for this variant. If + /// not specified then assembler variants will be determined based on + /// AsmString + string AsmVariantName = ""; + + ///@} + + /// UseNamedOperandTable - If set, the operand indices of this instruction + /// can be queried via the getNamedOperandIdx() function which is generated + /// by TableGen. + bit UseNamedOperandTable = 0; + + /// Should FastISel ignore this instruction. For certain ISAs, they have + /// instructions which map to the same ISD Opcode, value type operands and + /// instruction selection predicates. FastISel cannot handle such cases, but + /// SelectionDAG can. + bit FastISelShouldIgnore = 0; +} + +/// PseudoInstExpansion - Expansion information for a pseudo-instruction. +/// Which instruction it expands to and how the operands map from the +/// pseudo. +class PseudoInstExpansion<dag Result> { + dag ResultInst = Result; // The instruction to generate. + bit isPseudo = 1; +} + +/// Predicates - These are extra conditionals which are turned into instruction +/// selector matching code. Currently each predicate is just a string. +class Predicate<string cond> { + string CondString = cond; + + /// AssemblerMatcherPredicate - If this feature can be used by the assembler + /// matcher, this is true. Targets should set this by inheriting their + /// feature from the AssemblerPredicate class in addition to Predicate. + bit AssemblerMatcherPredicate = 0; + + /// AssemblerCondString - Name of the subtarget feature being tested used + /// as alternative condition string used for assembler matcher. + /// e.g. "ModeThumb" is translated to "(Bits & ModeThumb) != 0". + /// "!ModeThumb" is translated to "(Bits & ModeThumb) == 0". + /// It can also list multiple features separated by ",". + /// e.g. "ModeThumb,FeatureThumb2" is translated to + /// "(Bits & ModeThumb) != 0 && (Bits & FeatureThumb2) != 0". + string AssemblerCondString = ""; + + /// PredicateName - User-level name to use for the predicate. Mainly for use + /// in diagnostics such as missing feature errors in the asm matcher. + string PredicateName = ""; + + /// Setting this to '1' indicates that the predicate must be recomputed on + /// every function change. Most predicates can leave this at '0'. + /// + /// Ignored by SelectionDAG, it always recomputes the predicate on every use. + bit RecomputePerFunction = 0; +} + +/// NoHonorSignDependentRounding - This predicate is true if support for +/// sign-dependent-rounding is not enabled. +def NoHonorSignDependentRounding + : Predicate<"!TM.Options.HonorSignDependentRoundingFPMath()">; + +class Requires<list<Predicate> preds> { + list<Predicate> Predicates = preds; +} + +/// ops definition - This is just a simple marker used to identify the operand +/// list for an instruction. outs and ins are identical both syntactically and +/// semantically; they are used to define def operands and use operands to +/// improve readibility. This should be used like this: +/// (outs R32:$dst), (ins R32:$src1, R32:$src2) or something similar. +def ops; +def outs; +def ins; + +/// variable_ops definition - Mark this instruction as taking a variable number +/// of operands. +def variable_ops; + + +/// PointerLikeRegClass - Values that are designed to have pointer width are +/// derived from this. TableGen treats the register class as having a symbolic +/// type that it doesn't know, and resolves the actual regclass to use by using +/// the TargetRegisterInfo::getPointerRegClass() hook at codegen time. +class PointerLikeRegClass<int Kind> { + int RegClassKind = Kind; +} + + +/// ptr_rc definition - Mark this operand as being a pointer value whose +/// register class is resolved dynamically via a callback to TargetInstrInfo. +/// FIXME: We should probably change this to a class which contain a list of +/// flags. But currently we have but one flag. +def ptr_rc : PointerLikeRegClass<0>; + +/// unknown definition - Mark this operand as being of unknown type, causing +/// it to be resolved by inference in the context it is used. +class unknown_class; +def unknown : unknown_class; + +/// AsmOperandClass - Representation for the kinds of operands which the target +/// specific parser can create and the assembly matcher may need to distinguish. +/// +/// Operand classes are used to define the order in which instructions are +/// matched, to ensure that the instruction which gets matched for any +/// particular list of operands is deterministic. +/// +/// The target specific parser must be able to classify a parsed operand into a +/// unique class which does not partially overlap with any other classes. It can +/// match a subset of some other class, in which case the super class field +/// should be defined. +class AsmOperandClass { + /// The name to use for this class, which should be usable as an enum value. + string Name = ?; + + /// The super classes of this operand. + list<AsmOperandClass> SuperClasses = []; + + /// The name of the method on the target specific operand to call to test + /// whether the operand is an instance of this class. If not set, this will + /// default to "isFoo", where Foo is the AsmOperandClass name. The method + /// signature should be: + /// bool isFoo() const; + string PredicateMethod = ?; + + /// The name of the method on the target specific operand to call to add the + /// target specific operand to an MCInst. If not set, this will default to + /// "addFooOperands", where Foo is the AsmOperandClass name. The method + /// signature should be: + /// void addFooOperands(MCInst &Inst, unsigned N) const; + string RenderMethod = ?; + + /// The name of the method on the target specific operand to call to custom + /// handle the operand parsing. This is useful when the operands do not relate + /// to immediates or registers and are very instruction specific (as flags to + /// set in a processor register, coprocessor number, ...). + string ParserMethod = ?; + + // The diagnostic type to present when referencing this operand in a + // match failure error message. By default, use a generic "invalid operand" + // diagnostic. The target AsmParser maps these codes to text. + string DiagnosticType = ""; + + /// A diagnostic message to emit when an invalid value is provided for this + /// operand. + string DiagnosticString = ""; + + /// Set to 1 if this operand is optional and not always required. Typically, + /// the AsmParser will emit an error when it finishes parsing an + /// instruction if it hasn't matched all the operands yet. However, this + /// error will be suppressed if all of the remaining unmatched operands are + /// marked as IsOptional. + /// + /// Optional arguments must be at the end of the operand list. + bit IsOptional = 0; + + /// The name of the method on the target specific asm parser that returns the + /// default operand for this optional operand. This method is only used if + /// IsOptional == 1. If not set, this will default to "defaultFooOperands", + /// where Foo is the AsmOperandClass name. The method signature should be: + /// std::unique_ptr<MCParsedAsmOperand> defaultFooOperands() const; + string DefaultMethod = ?; +} + +def ImmAsmOperand : AsmOperandClass { + let Name = "Imm"; +} + +/// Operand Types - These provide the built-in operand types that may be used +/// by a target. Targets can optionally provide their own operand types as +/// needed, though this should not be needed for RISC targets. +class Operand<ValueType ty> : DAGOperand { + ValueType Type = ty; + string PrintMethod = "printOperand"; + string EncoderMethod = ""; + bit hasCompleteDecoder = 1; + string OperandType = "OPERAND_UNKNOWN"; + dag MIOperandInfo = (ops); + + // MCOperandPredicate - Optionally, a code fragment operating on + // const MCOperand &MCOp, and returning a bool, to indicate if + // the value of MCOp is valid for the specific subclass of Operand + code MCOperandPredicate; + + // ParserMatchClass - The "match class" that operands of this type fit + // in. Match classes are used to define the order in which instructions are + // match, to ensure that which instructions gets matched is deterministic. + // + // The target specific parser must be able to classify an parsed operand into + // a unique class, which does not partially overlap with any other classes. It + // can match a subset of some other class, in which case the AsmOperandClass + // should declare the other operand as one of its super classes. + AsmOperandClass ParserMatchClass = ImmAsmOperand; +} + +class RegisterOperand<RegisterClass regclass, string pm = "printOperand"> + : DAGOperand { + // RegClass - The register class of the operand. + RegisterClass RegClass = regclass; + // PrintMethod - The target method to call to print register operands of + // this type. The method normally will just use an alt-name index to look + // up the name to print. Default to the generic printOperand(). + string PrintMethod = pm; + + // EncoderMethod - The target method name to call to encode this register + // operand. + string EncoderMethod = ""; + + // ParserMatchClass - The "match class" that operands of this type fit + // in. Match classes are used to define the order in which instructions are + // match, to ensure that which instructions gets matched is deterministic. + // + // The target specific parser must be able to classify an parsed operand into + // a unique class, which does not partially overlap with any other classes. It + // can match a subset of some other class, in which case the AsmOperandClass + // should declare the other operand as one of its super classes. + AsmOperandClass ParserMatchClass; + + string OperandType = "OPERAND_REGISTER"; + + // When referenced in the result of a CodeGen pattern, GlobalISel will + // normally copy the matched operand to the result. When this is set, it will + // emit a special copy that will replace zero-immediates with the specified + // zero-register. + Register GIZeroRegister = ?; +} + +let OperandType = "OPERAND_IMMEDIATE" in { +def i1imm : Operand<i1>; +def i8imm : Operand<i8>; +def i16imm : Operand<i16>; +def i32imm : Operand<i32>; +def i64imm : Operand<i64>; + +def f32imm : Operand<f32>; +def f64imm : Operand<f64>; +} + +// Register operands for generic instructions don't have an MVT, but do have +// constraints linking the operands (e.g. all operands of a G_ADD must +// have the same LLT). +class TypedOperand<string Ty> : Operand<untyped> { + let OperandType = Ty; + bit IsPointer = 0; +} + +def type0 : TypedOperand<"OPERAND_GENERIC_0">; +def type1 : TypedOperand<"OPERAND_GENERIC_1">; +def type2 : TypedOperand<"OPERAND_GENERIC_2">; +def type3 : TypedOperand<"OPERAND_GENERIC_3">; +def type4 : TypedOperand<"OPERAND_GENERIC_4">; +def type5 : TypedOperand<"OPERAND_GENERIC_5">; + +let IsPointer = 1 in { + def ptype0 : TypedOperand<"OPERAND_GENERIC_0">; + def ptype1 : TypedOperand<"OPERAND_GENERIC_1">; + def ptype2 : TypedOperand<"OPERAND_GENERIC_2">; + def ptype3 : TypedOperand<"OPERAND_GENERIC_3">; + def ptype4 : TypedOperand<"OPERAND_GENERIC_4">; + def ptype5 : TypedOperand<"OPERAND_GENERIC_5">; +} + +/// zero_reg definition - Special node to stand for the zero register. +/// +def zero_reg; + +/// All operands which the MC layer classifies as predicates should inherit from +/// this class in some manner. This is already handled for the most commonly +/// used PredicateOperand, but may be useful in other circumstances. +class PredicateOp; + +/// OperandWithDefaultOps - This Operand class can be used as the parent class +/// for an Operand that needs to be initialized with a default value if +/// no value is supplied in a pattern. This class can be used to simplify the +/// pattern definitions for instructions that have target specific flags +/// encoded as immediate operands. +class OperandWithDefaultOps<ValueType ty, dag defaultops> + : Operand<ty> { + dag DefaultOps = defaultops; +} + +/// PredicateOperand - This can be used to define a predicate operand for an +/// instruction. OpTypes specifies the MIOperandInfo for the operand, and +/// AlwaysVal specifies the value of this predicate when set to "always +/// execute". +class PredicateOperand<ValueType ty, dag OpTypes, dag AlwaysVal> + : OperandWithDefaultOps<ty, AlwaysVal>, PredicateOp { + let MIOperandInfo = OpTypes; +} + +/// OptionalDefOperand - This is used to define a optional definition operand +/// for an instruction. DefaultOps is the register the operand represents if +/// none is supplied, e.g. zero_reg. +class OptionalDefOperand<ValueType ty, dag OpTypes, dag defaultops> + : OperandWithDefaultOps<ty, defaultops> { + let MIOperandInfo = OpTypes; +} + + +// InstrInfo - This class should only be instantiated once to provide parameters +// which are global to the target machine. +// +class InstrInfo { + // Target can specify its instructions in either big or little-endian formats. + // For instance, while both Sparc and PowerPC are big-endian platforms, the + // Sparc manual specifies its instructions in the format [31..0] (big), while + // PowerPC specifies them using the format [0..31] (little). + bit isLittleEndianEncoding = 0; + + // The instruction properties mayLoad, mayStore, and hasSideEffects are unset + // by default, and TableGen will infer their value from the instruction + // pattern when possible. + // + // Normally, TableGen will issue an error it it can't infer the value of a + // property that hasn't been set explicitly. When guessInstructionProperties + // is set, it will guess a safe value instead. + // + // This option is a temporary migration help. It will go away. + bit guessInstructionProperties = 1; + + // TableGen's instruction encoder generator has support for matching operands + // to bit-field variables both by name and by position. While matching by + // name is preferred, this is currently not possible for complex operands, + // and some targets still reply on the positional encoding rules. When + // generating a decoder for such targets, the positional encoding rules must + // be used by the decoder generator as well. + // + // This option is temporary; it will go away once the TableGen decoder + // generator has better support for complex operands and targets have + // migrated away from using positionally encoded operands. + bit decodePositionallyEncodedOperands = 0; + + // When set, this indicates that there will be no overlap between those + // operands that are matched by ordering (positional operands) and those + // matched by name. + // + // This option is temporary; it will go away once the TableGen decoder + // generator has better support for complex operands and targets have + // migrated away from using positionally encoded operands. + bit noNamedPositionallyEncodedOperands = 0; +} + +// Standard Pseudo Instructions. +// This list must match TargetOpcodes.h and CodeGenTarget.cpp. +// Only these instructions are allowed in the TargetOpcode namespace. +// Ensure mayLoad and mayStore have a default value, so as not to break +// targets that set guessInstructionProperties=0. Any local definition of +// mayLoad/mayStore takes precedence over these default values. +class StandardPseudoInstruction : Instruction { + let mayLoad = 0; + let mayStore = 0; + let isCodeGenOnly = 1; + let isPseudo = 1; + let hasNoSchedulingInfo = 1; + let Namespace = "TargetOpcode"; +} +def PHI : StandardPseudoInstruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins variable_ops); + let AsmString = "PHINODE"; + let hasSideEffects = 0; +} +def INLINEASM : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins variable_ops); + let AsmString = ""; + let hasSideEffects = 0; // Note side effect is encoded in an operand. +} +def CFI_INSTRUCTION : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins i32imm:$id); + let AsmString = ""; + let hasCtrlDep = 1; + let hasSideEffects = 0; + let isNotDuplicable = 1; +} +def EH_LABEL : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins i32imm:$id); + let AsmString = ""; + let hasCtrlDep = 1; + let hasSideEffects = 0; + let isNotDuplicable = 1; +} +def GC_LABEL : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins i32imm:$id); + let AsmString = ""; + let hasCtrlDep = 1; + let hasSideEffects = 0; + let isNotDuplicable = 1; +} +def ANNOTATION_LABEL : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins i32imm:$id); + let AsmString = ""; + let hasCtrlDep = 1; + let hasSideEffects = 0; + let isNotDuplicable = 1; +} +def KILL : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins variable_ops); + let AsmString = ""; + let hasSideEffects = 0; +} +def EXTRACT_SUBREG : StandardPseudoInstruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins unknown:$supersrc, i32imm:$subidx); + let AsmString = ""; + let hasSideEffects = 0; +} +def INSERT_SUBREG : StandardPseudoInstruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins unknown:$supersrc, unknown:$subsrc, i32imm:$subidx); + let AsmString = ""; + let hasSideEffects = 0; + let Constraints = "$supersrc = $dst"; +} +def IMPLICIT_DEF : StandardPseudoInstruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins); + let AsmString = ""; + let hasSideEffects = 0; + let isReMaterializable = 1; + let isAsCheapAsAMove = 1; +} +def SUBREG_TO_REG : StandardPseudoInstruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins unknown:$implsrc, unknown:$subsrc, i32imm:$subidx); + let AsmString = ""; + let hasSideEffects = 0; +} +def COPY_TO_REGCLASS : StandardPseudoInstruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins unknown:$src, i32imm:$regclass); + let AsmString = ""; + let hasSideEffects = 0; + let isAsCheapAsAMove = 1; +} +def DBG_VALUE : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins variable_ops); + let AsmString = "DBG_VALUE"; + let hasSideEffects = 0; +} +def DBG_LABEL : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins unknown:$label); + let AsmString = "DBG_LABEL"; + let hasSideEffects = 0; +} +def REG_SEQUENCE : StandardPseudoInstruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins unknown:$supersrc, variable_ops); + let AsmString = ""; + let hasSideEffects = 0; + let isAsCheapAsAMove = 1; +} +def COPY : StandardPseudoInstruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins unknown:$src); + let AsmString = ""; + let hasSideEffects = 0; + let isAsCheapAsAMove = 1; + let hasNoSchedulingInfo = 0; +} +def BUNDLE : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins variable_ops); + let AsmString = "BUNDLE"; + let hasSideEffects = 1; +} +def LIFETIME_START : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins i32imm:$id); + let AsmString = "LIFETIME_START"; + let hasSideEffects = 0; +} +def LIFETIME_END : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins i32imm:$id); + let AsmString = "LIFETIME_END"; + let hasSideEffects = 0; +} +def STACKMAP : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins i64imm:$id, i32imm:$nbytes, variable_ops); + let hasSideEffects = 1; + let isCall = 1; + let mayLoad = 1; + let usesCustomInserter = 1; +} +def PATCHPOINT : StandardPseudoInstruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins i64imm:$id, i32imm:$nbytes, unknown:$callee, + i32imm:$nargs, i32imm:$cc, variable_ops); + let hasSideEffects = 1; + let isCall = 1; + let mayLoad = 1; + let usesCustomInserter = 1; +} +def STATEPOINT : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins variable_ops); + let usesCustomInserter = 1; + let mayLoad = 1; + let mayStore = 1; + let hasSideEffects = 1; + let isCall = 1; +} +def LOAD_STACK_GUARD : StandardPseudoInstruction { + let OutOperandList = (outs ptr_rc:$dst); + let InOperandList = (ins); + let mayLoad = 1; + bit isReMaterializable = 1; + let hasSideEffects = 0; + bit isPseudo = 1; +} +def LOCAL_ESCAPE : StandardPseudoInstruction { + // This instruction is really just a label. It has to be part of the chain so + // that it doesn't get dropped from the DAG, but it produces nothing and has + // no side effects. + let OutOperandList = (outs); + let InOperandList = (ins ptr_rc:$symbol, i32imm:$id); + let hasSideEffects = 0; + let hasCtrlDep = 1; +} +def FAULTING_OP : StandardPseudoInstruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins variable_ops); + let usesCustomInserter = 1; + let hasSideEffects = 1; + let mayLoad = 1; + let mayStore = 1; + let isTerminator = 1; + let isBranch = 1; +} +def PATCHABLE_OP : StandardPseudoInstruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins variable_ops); + let usesCustomInserter = 1; + let mayLoad = 1; + let mayStore = 1; + let hasSideEffects = 1; +} +def PATCHABLE_FUNCTION_ENTER : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins); + let AsmString = "# XRay Function Enter."; + let usesCustomInserter = 1; + let hasSideEffects = 0; +} +def PATCHABLE_RET : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins variable_ops); + let AsmString = "# XRay Function Patchable RET."; + let usesCustomInserter = 1; + let hasSideEffects = 1; + let isTerminator = 1; + let isReturn = 1; +} +def PATCHABLE_FUNCTION_EXIT : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins); + let AsmString = "# XRay Function Exit."; + let usesCustomInserter = 1; + let hasSideEffects = 0; // FIXME: is this correct? + let isReturn = 0; // Original return instruction will follow +} +def PATCHABLE_TAIL_CALL : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins variable_ops); + let AsmString = "# XRay Tail Call Exit."; + let usesCustomInserter = 1; + let hasSideEffects = 1; + let isReturn = 1; +} +def PATCHABLE_EVENT_CALL : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins ptr_rc:$event, i8imm:$size); + let AsmString = "# XRay Custom Event Log."; + let usesCustomInserter = 1; + let isCall = 1; + let mayLoad = 1; + let mayStore = 1; + let hasSideEffects = 1; +} +def PATCHABLE_TYPED_EVENT_CALL : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins i16imm:$type, ptr_rc:$event, i32imm:$size); + let AsmString = "# XRay Typed Event Log."; + let usesCustomInserter = 1; + let isCall = 1; + let mayLoad = 1; + let mayStore = 1; + let hasSideEffects = 1; +} +def FENTRY_CALL : StandardPseudoInstruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins variable_ops); + let AsmString = "# FEntry call"; + let usesCustomInserter = 1; + let mayLoad = 1; + let mayStore = 1; + let hasSideEffects = 1; +} +def ICALL_BRANCH_FUNNEL : StandardPseudoInstruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins variable_ops); + let AsmString = ""; + let hasSideEffects = 1; +} + +// Generic opcodes used in GlobalISel. +include "llvm/Target/GenericOpcodes.td" + +//===----------------------------------------------------------------------===// +// AsmParser - This class can be implemented by targets that wish to implement +// .s file parsing. +// +// Subtargets can have multiple different assembly parsers (e.g. AT&T vs Intel +// syntax on X86 for example). +// +class AsmParser { + // AsmParserClassName - This specifies the suffix to use for the asmparser + // class. Generated AsmParser classes are always prefixed with the target + // name. + string AsmParserClassName = "AsmParser"; + + // AsmParserInstCleanup - If non-empty, this is the name of a custom member + // function of the AsmParser class to call on every matched instruction. + // This can be used to perform target specific instruction post-processing. + string AsmParserInstCleanup = ""; + + // ShouldEmitMatchRegisterName - Set to false if the target needs a hand + // written register name matcher + bit ShouldEmitMatchRegisterName = 1; + + // Set to true if the target needs a generated 'alternative register name' + // matcher. + // + // This generates a function which can be used to lookup registers from + // their aliases. This function will fail when called on targets where + // several registers share the same alias (i.e. not a 1:1 mapping). + bit ShouldEmitMatchRegisterAltName = 0; + + // Set to true if MatchRegisterName and MatchRegisterAltName functions + // should be generated even if there are duplicate register names. The + // target is responsible for coercing aliased registers as necessary + // (e.g. in validateTargetOperandClass), and there are no guarantees about + // which numeric register identifier will be returned in the case of + // multiple matches. + bit AllowDuplicateRegisterNames = 0; + + // HasMnemonicFirst - Set to false if target instructions don't always + // start with a mnemonic as the first token. + bit HasMnemonicFirst = 1; + + // ReportMultipleNearMisses - + // When 0, the assembly matcher reports an error for one encoding or operand + // that did not match the parsed instruction. + // When 1, the assmebly matcher returns a list of encodings that were close + // to matching the parsed instruction, so to allow more detailed error + // messages. + bit ReportMultipleNearMisses = 0; +} +def DefaultAsmParser : AsmParser; + +//===----------------------------------------------------------------------===// +// AsmParserVariant - Subtargets can have multiple different assembly parsers +// (e.g. AT&T vs Intel syntax on X86 for example). This class can be +// implemented by targets to describe such variants. +// +class AsmParserVariant { + // Variant - AsmParsers can be of multiple different variants. Variants are + // used to support targets that need to parser multiple formats for the + // assembly language. + int Variant = 0; + + // Name - The AsmParser variant name (e.g., AT&T vs Intel). + string Name = ""; + + // CommentDelimiter - If given, the delimiter string used to recognize + // comments which are hard coded in the .td assembler strings for individual + // instructions. + string CommentDelimiter = ""; + + // RegisterPrefix - If given, the token prefix which indicates a register + // token. This is used by the matcher to automatically recognize hard coded + // register tokens as constrained registers, instead of tokens, for the + // purposes of matching. + string RegisterPrefix = ""; + + // TokenizingCharacters - Characters that are standalone tokens + string TokenizingCharacters = "[]*!"; + + // SeparatorCharacters - Characters that are not tokens + string SeparatorCharacters = " \t,"; + + // BreakCharacters - Characters that start new identifiers + string BreakCharacters = ""; +} +def DefaultAsmParserVariant : AsmParserVariant; + +/// AssemblerPredicate - This is a Predicate that can be used when the assembler +/// matches instructions and aliases. +class AssemblerPredicate<string cond, string name = ""> { + bit AssemblerMatcherPredicate = 1; + string AssemblerCondString = cond; + string PredicateName = name; +} + +/// TokenAlias - This class allows targets to define assembler token +/// operand aliases. That is, a token literal operand which is equivalent +/// to another, canonical, token literal. For example, ARM allows: +/// vmov.u32 s4, #0 -> vmov.i32, #0 +/// 'u32' is a more specific designator for the 32-bit integer type specifier +/// and is legal for any instruction which accepts 'i32' as a datatype suffix. +/// def : TokenAlias<".u32", ".i32">; +/// +/// This works by marking the match class of 'From' as a subclass of the +/// match class of 'To'. +class TokenAlias<string From, string To> { + string FromToken = From; + string ToToken = To; +} + +/// MnemonicAlias - This class allows targets to define assembler mnemonic +/// aliases. This should be used when all forms of one mnemonic are accepted +/// with a different mnemonic. For example, X86 allows: +/// sal %al, 1 -> shl %al, 1 +/// sal %ax, %cl -> shl %ax, %cl +/// sal %eax, %cl -> shl %eax, %cl +/// etc. Though "sal" is accepted with many forms, all of them are directly +/// translated to a shl, so it can be handled with (in the case of X86, it +/// actually has one for each suffix as well): +/// def : MnemonicAlias<"sal", "shl">; +/// +/// Mnemonic aliases are mapped before any other translation in the match phase, +/// and do allow Requires predicates, e.g.: +/// +/// def : MnemonicAlias<"pushf", "pushfq">, Requires<[In64BitMode]>; +/// def : MnemonicAlias<"pushf", "pushfl">, Requires<[In32BitMode]>; +/// +/// Mnemonic aliases can also be constrained to specific variants, e.g.: +/// +/// def : MnemonicAlias<"pushf", "pushfq", "att">, Requires<[In64BitMode]>; +/// +/// If no variant (e.g., "att" or "intel") is specified then the alias is +/// applied unconditionally. +class MnemonicAlias<string From, string To, string VariantName = ""> { + string FromMnemonic = From; + string ToMnemonic = To; + string AsmVariantName = VariantName; + + // Predicates - Predicates that must be true for this remapping to happen. + list<Predicate> Predicates = []; +} + +/// InstAlias - This defines an alternate assembly syntax that is allowed to +/// match an instruction that has a different (more canonical) assembly +/// representation. +class InstAlias<string Asm, dag Result, int Emit = 1, string VariantName = ""> { + string AsmString = Asm; // The .s format to match the instruction with. + dag ResultInst = Result; // The MCInst to generate. + + // This determines which order the InstPrinter detects aliases for + // printing. A larger value makes the alias more likely to be + // emitted. The Instruction's own definition is notionally 0.5, so 0 + // disables printing and 1 enables it if there are no conflicting aliases. + int EmitPriority = Emit; + + // Predicates - Predicates that must be true for this to match. + list<Predicate> Predicates = []; + + // If the instruction specified in Result has defined an AsmMatchConverter + // then setting this to 1 will cause the alias to use the AsmMatchConverter + // function when converting the OperandVector into an MCInst instead of the + // function that is generated by the dag Result. + // Setting this to 0 will cause the alias to ignore the Result instruction's + // defined AsmMatchConverter and instead use the function generated by the + // dag Result. + bit UseInstAsmMatchConverter = 1; + + // Assembler variant name to use for this alias. If not specified then + // assembler variants will be determined based on AsmString + string AsmVariantName = VariantName; +} + +//===----------------------------------------------------------------------===// +// AsmWriter - This class can be implemented by targets that need to customize +// the format of the .s file writer. +// +// Subtargets can have multiple different asmwriters (e.g. AT&T vs Intel syntax +// on X86 for example). +// +class AsmWriter { + // AsmWriterClassName - This specifies the suffix to use for the asmwriter + // class. Generated AsmWriter classes are always prefixed with the target + // name. + string AsmWriterClassName = "InstPrinter"; + + // PassSubtarget - Determines whether MCSubtargetInfo should be passed to + // the various print methods. + // FIXME: Remove after all ports are updated. + int PassSubtarget = 0; + + // Variant - AsmWriters can be of multiple different variants. Variants are + // used to support targets that need to emit assembly code in ways that are + // mostly the same for different targets, but have minor differences in + // syntax. If the asmstring contains {|} characters in them, this integer + // will specify which alternative to use. For example "{x|y|z}" with Variant + // == 1, will expand to "y". + int Variant = 0; +} +def DefaultAsmWriter : AsmWriter; + + +//===----------------------------------------------------------------------===// +// Target - This class contains the "global" target information +// +class Target { + // InstructionSet - Instruction set description for this target. + InstrInfo InstructionSet; + + // AssemblyParsers - The AsmParser instances available for this target. + list<AsmParser> AssemblyParsers = [DefaultAsmParser]; + + /// AssemblyParserVariants - The AsmParserVariant instances available for + /// this target. + list<AsmParserVariant> AssemblyParserVariants = [DefaultAsmParserVariant]; + + // AssemblyWriters - The AsmWriter instances available for this target. + list<AsmWriter> AssemblyWriters = [DefaultAsmWriter]; + + // AllowRegisterRenaming - Controls whether this target allows + // post-register-allocation renaming of registers. This is done by + // setting hasExtraDefRegAllocReq and hasExtraSrcRegAllocReq to 1 + // for all opcodes if this flag is set to 0. + int AllowRegisterRenaming = 0; +} + +//===----------------------------------------------------------------------===// +// SubtargetFeature - A characteristic of the chip set. +// +class SubtargetFeature<string n, string a, string v, string d, + list<SubtargetFeature> i = []> { + // Name - Feature name. Used by command line (-mattr=) to determine the + // appropriate target chip. + // + string Name = n; + + // Attribute - Attribute to be set by feature. + // + string Attribute = a; + + // Value - Value the attribute to be set to by feature. + // + string Value = v; + + // Desc - Feature description. Used by command line (-mattr=) to display help + // information. + // + string Desc = d; + + // Implies - Features that this feature implies are present. If one of those + // features isn't set, then this one shouldn't be set either. + // + list<SubtargetFeature> Implies = i; +} + +/// Specifies a Subtarget feature that this instruction is deprecated on. +class Deprecated<SubtargetFeature dep> { + SubtargetFeature DeprecatedFeatureMask = dep; +} + +/// A custom predicate used to determine if an instruction is +/// deprecated or not. +class ComplexDeprecationPredicate<string dep> { + string ComplexDeprecationPredicate = dep; +} + +//===----------------------------------------------------------------------===// +// Processor chip sets - These values represent each of the chip sets supported +// by the scheduler. Each Processor definition requires corresponding +// instruction itineraries. +// +class Processor<string n, ProcessorItineraries pi, list<SubtargetFeature> f> { + // Name - Chip set name. Used by command line (-mcpu=) to determine the + // appropriate target chip. + // + string Name = n; + + // SchedModel - The machine model for scheduling and instruction cost. + // + SchedMachineModel SchedModel = NoSchedModel; + + // ProcItin - The scheduling information for the target processor. + // + ProcessorItineraries ProcItin = pi; + + // Features - list of + list<SubtargetFeature> Features = f; +} + +// ProcessorModel allows subtargets to specify the more general +// SchedMachineModel instead if a ProcessorItinerary. Subtargets will +// gradually move to this newer form. +// +// Although this class always passes NoItineraries to the Processor +// class, the SchedMachineModel may still define valid Itineraries. +class ProcessorModel<string n, SchedMachineModel m, list<SubtargetFeature> f> + : Processor<n, NoItineraries, f> { + let SchedModel = m; +} + +//===----------------------------------------------------------------------===// +// InstrMapping - This class is used to create mapping tables to relate +// instructions with each other based on the values specified in RowFields, +// ColFields, KeyCol and ValueCols. +// +class InstrMapping { + // FilterClass - Used to limit search space only to the instructions that + // define the relationship modeled by this InstrMapping record. + string FilterClass; + + // RowFields - List of fields/attributes that should be same for all the + // instructions in a row of the relation table. Think of this as a set of + // properties shared by all the instructions related by this relationship + // model and is used to categorize instructions into subgroups. For instance, + // if we want to define a relation that maps 'Add' instruction to its + // predicated forms, we can define RowFields like this: + // + // let RowFields = BaseOp + // All add instruction predicated/non-predicated will have to set their BaseOp + // to the same value. + // + // def Add: { let BaseOp = 'ADD'; let predSense = 'nopred' } + // def Add_predtrue: { let BaseOp = 'ADD'; let predSense = 'true' } + // def Add_predfalse: { let BaseOp = 'ADD'; let predSense = 'false' } + list<string> RowFields = []; + + // List of fields/attributes that are same for all the instructions + // in a column of the relation table. + // Ex: let ColFields = 'predSense' -- It means that the columns are arranged + // based on the 'predSense' values. All the instruction in a specific + // column have the same value and it is fixed for the column according + // to the values set in 'ValueCols'. + list<string> ColFields = []; + + // Values for the fields/attributes listed in 'ColFields'. + // Ex: let KeyCol = 'nopred' -- It means that the key instruction (instruction + // that models this relation) should be non-predicated. + // In the example above, 'Add' is the key instruction. + list<string> KeyCol = []; + + // List of values for the fields/attributes listed in 'ColFields', one for + // each column in the relation table. + // + // Ex: let ValueCols = [['true'],['false']] -- It adds two columns in the + // table. First column requires all the instructions to have predSense + // set to 'true' and second column requires it to be 'false'. + list<list<string> > ValueCols = []; +} + +//===----------------------------------------------------------------------===// +// Pull in the common support for calling conventions. +// +include "llvm/Target/TargetCallingConv.td" + +//===----------------------------------------------------------------------===// +// Pull in the common support for DAG isel generation. +// +include "llvm/Target/TargetSelectionDAG.td" + +//===----------------------------------------------------------------------===// +// Pull in the common support for Global ISel register bank info generation. +// +include "llvm/Target/GlobalISel/RegisterBank.td" + +//===----------------------------------------------------------------------===// +// Pull in the common support for DAG isel generation. +// +include "llvm/Target/GlobalISel/Target.td" + +//===----------------------------------------------------------------------===// +// Pull in the common support for the Global ISel DAG-based selector generation. +// +include "llvm/Target/GlobalISel/SelectionDAGCompat.td" diff --git a/capstone/suite/synctools/tablegen/include/llvm/Target/TargetCallingConv.td b/capstone/suite/synctools/tablegen/include/llvm/Target/TargetCallingConv.td new file mode 100644 index 000000000..95d2b4226 --- /dev/null +++ b/capstone/suite/synctools/tablegen/include/llvm/Target/TargetCallingConv.td @@ -0,0 +1,187 @@ +//===- TargetCallingConv.td - Target Calling Conventions ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the target-independent interfaces with which targets +// describe their calling conventions. +// +//===----------------------------------------------------------------------===// + +class CCAction; +class CallingConv; + +/// CCCustom - Calls a custom arg handling function. +class CCCustom<string fn> : CCAction { + string FuncName = fn; +} + +/// CCPredicateAction - Instances of this class check some predicate, then +/// delegate to another action if the predicate is true. +class CCPredicateAction<CCAction A> : CCAction { + CCAction SubAction = A; +} + +/// CCIfType - If the current argument is one of the specified types, apply +/// Action A. +class CCIfType<list<ValueType> vts, CCAction A> : CCPredicateAction<A> { + list<ValueType> VTs = vts; +} + +/// CCIf - If the predicate matches, apply A. +class CCIf<string predicate, CCAction A> : CCPredicateAction<A> { + string Predicate = predicate; +} + +/// CCIfByVal - If the current argument has ByVal parameter attribute, apply +/// Action A. +class CCIfByVal<CCAction A> : CCIf<"ArgFlags.isByVal()", A> { +} + +/// CCIfSwiftSelf - If the current argument has swiftself parameter attribute, +/// apply Action A. +class CCIfSwiftSelf<CCAction A> : CCIf<"ArgFlags.isSwiftSelf()", A> { +} + +/// CCIfSwiftError - If the current argument has swifterror parameter attribute, +/// apply Action A. +class CCIfSwiftError<CCAction A> : CCIf<"ArgFlags.isSwiftError()", A> { +} + +/// CCIfConsecutiveRegs - If the current argument has InConsecutiveRegs +/// parameter attribute, apply Action A. +class CCIfConsecutiveRegs<CCAction A> : CCIf<"ArgFlags.isInConsecutiveRegs()", A> { +} + +/// CCIfCC - Match if the current calling convention is 'CC'. +class CCIfCC<string CC, CCAction A> + : CCIf<!strconcat("State.getCallingConv() == ", CC), A> {} + +/// CCIfInReg - If this argument is marked with the 'inreg' attribute, apply +/// the specified action. +class CCIfInReg<CCAction A> : CCIf<"ArgFlags.isInReg()", A> {} + +/// CCIfNest - If this argument is marked with the 'nest' attribute, apply +/// the specified action. +class CCIfNest<CCAction A> : CCIf<"ArgFlags.isNest()", A> {} + +/// CCIfSplit - If this argument is marked with the 'split' attribute, apply +/// the specified action. +class CCIfSplit<CCAction A> : CCIf<"ArgFlags.isSplit()", A> {} + +/// CCIfSRet - If this argument is marked with the 'sret' attribute, apply +/// the specified action. +class CCIfSRet<CCAction A> : CCIf<"ArgFlags.isSRet()", A> {} + +/// CCIfVarArg - If the current function is vararg - apply the action +class CCIfVarArg<CCAction A> : CCIf<"State.isVarArg()", A> {} + +/// CCIfNotVarArg - If the current function is not vararg - apply the action +class CCIfNotVarArg<CCAction A> : CCIf<"!State.isVarArg()", A> {} + +/// CCAssignToReg - This action matches if there is a register in the specified +/// list that is still available. If so, it assigns the value to the first +/// available register and succeeds. +class CCAssignToReg<list<Register> regList> : CCAction { + list<Register> RegList = regList; +} + +/// CCAssignToRegWithShadow - Same as CCAssignToReg, but with list of registers +/// which became shadowed, when some register is used. +class CCAssignToRegWithShadow<list<Register> regList, + list<Register> shadowList> : CCAction { + list<Register> RegList = regList; + list<Register> ShadowRegList = shadowList; +} + +/// CCAssignToStack - This action always matches: it assigns the value to a +/// stack slot of the specified size and alignment on the stack. If size is +/// zero then the ABI size is used; if align is zero then the ABI alignment +/// is used - these may depend on the target or subtarget. +class CCAssignToStack<int size, int align> : CCAction { + int Size = size; + int Align = align; +} + +/// CCAssignToStackWithShadow - Same as CCAssignToStack, but with a list of +/// registers to be shadowed. Note that, unlike CCAssignToRegWithShadow, this +/// shadows ALL of the registers in shadowList. +class CCAssignToStackWithShadow<int size, + int align, + list<Register> shadowList> : CCAction { + int Size = size; + int Align = align; + list<Register> ShadowRegList = shadowList; +} + +/// CCPassByVal - This action always matches: it assigns the value to a stack +/// slot to implement ByVal aggregate parameter passing. Size and alignment +/// specify the minimum size and alignment for the stack slot. +class CCPassByVal<int size, int align> : CCAction { + int Size = size; + int Align = align; +} + +/// CCPromoteToType - If applied, this promotes the specified current value to +/// the specified type. +class CCPromoteToType<ValueType destTy> : CCAction { + ValueType DestTy = destTy; +} + +/// CCPromoteToUpperBitsInType - If applied, this promotes the specified current +/// value to the specified type and shifts the value into the upper bits. +class CCPromoteToUpperBitsInType<ValueType destTy> : CCAction { + ValueType DestTy = destTy; +} + +/// CCBitConvertToType - If applied, this bitconverts the specified current +/// value to the specified type. +class CCBitConvertToType<ValueType destTy> : CCAction { + ValueType DestTy = destTy; +} + +/// CCPassIndirect - If applied, this stores the value to stack and passes the pointer +/// as normal argument. +class CCPassIndirect<ValueType destTy> : CCAction { + ValueType DestTy = destTy; +} + +/// CCDelegateTo - This action invokes the specified sub-calling-convention. It +/// is successful if the specified CC matches. +class CCDelegateTo<CallingConv cc> : CCAction { + CallingConv CC = cc; +} + +/// CallingConv - An instance of this is used to define each calling convention +/// that the target supports. +class CallingConv<list<CCAction> actions> { + list<CCAction> Actions = actions; + bit Custom = 0; +} + +/// CustomCallingConv - An instance of this is used to declare calling +/// conventions that are implemented using a custom function of the same name. +class CustomCallingConv : CallingConv<[]> { + let Custom = 1; +} + +/// CalleeSavedRegs - A list of callee saved registers for a given calling +/// convention. The order of registers is used by PrologEpilogInsertion when +/// allocation stack slots for saved registers. +/// +/// For each CalleeSavedRegs def, TableGen will emit a FOO_SaveList array for +/// returning from getCalleeSavedRegs(), and a FOO_RegMask bit mask suitable for +/// returning from getCallPreservedMask(). +class CalleeSavedRegs<dag saves> { + dag SaveList = saves; + + // Registers that are also preserved across function calls, but should not be + // included in the generated FOO_SaveList array. These registers will be + // included in the FOO_RegMask bit mask. This can be used for registers that + // are saved automatically, like the SPARC register windows. + dag OtherPreserved; +} diff --git a/capstone/suite/synctools/tablegen/include/llvm/Target/TargetInstrPredicate.td b/capstone/suite/synctools/tablegen/include/llvm/Target/TargetInstrPredicate.td new file mode 100644 index 000000000..8d57cae02 --- /dev/null +++ b/capstone/suite/synctools/tablegen/include/llvm/Target/TargetInstrPredicate.td @@ -0,0 +1,197 @@ +//===- TargetInstrPredicate.td - ---------------------------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines MCInstPredicate classes and its subclasses. +// +// MCInstPredicate is used to describe constraints on the opcode/operand(s) of +// an instruction. Each MCInstPredicate class has a well-known semantic, and it +// is used by a PredicateExpander to generate code for MachineInstr and/or +// MCInst. +// +// MCInstPredicate definitions can be used to construct MCSchedPredicate +// definitions. An MCSchedPredicate can be used in place of a SchedPredicate +// when defining SchedReadVariant and SchedWriteVariant used by a processor +// scheduling model. +// +// Here is an example of MCInstPredicate definition: +// +// def MCInstPredicateExample : CheckAll<[ +// CheckOpcode<[BLR]>, +// CheckIsRegOperand<0>, +// CheckNot<CheckRegOperand<0, LR>>]>; +// +// Predicate `MCInstPredicateExample` checks that the machine instruction in +// input is a BLR, and that operand at index 0 is register `LR`. +// +// That predicate could be used to rewrite the following definition (from +// AArch64SchedExynosM3.td): +// +// def M3BranchLinkFastPred : SchedPredicate<[{ +// MI->getOpcode() == AArch64::BLR && +// MI->getOperand(0).isReg() && +// MI->getOperand(0).getReg() != AArch64::LR}]>; +// +// MCInstPredicate definitions are used to construct MCSchedPredicate (see the +// definition of class MCSchedPredicate in llvm/Target/TargetSchedule.td). An +// MCSchedPredicate can be used by a `SchedVar` to associate a predicate with a +// list of SchedReadWrites. Note that `SchedVar` are used to create SchedVariant +// definitions. +// +// Each MCInstPredicate class has a well known semantic. For example, +// `CheckOpcode` is only used to check the instruction opcode value. +// +// MCInstPredicate classes allow the definition of predicates in a declarative +// way. These predicates don't require a custom block of C++, and can be used +// to define conditions on instructions without being bound to a particular +// representation (i.e. MachineInstr vs MCInst). +// +// It also means that tablegen backends must know how to parse and expand them +// into code that works on MCInst (or MachineInst). +// +// Instances of class PredicateExpander (see utils/Tablegen/PredicateExpander.h) +// know how to expand a predicate. For each MCInstPredicate class, there must be +// an "expand" method available in the PredicateExpander interface. +// +// For example, a `CheckOpcode` predicate is expanded using method +// `PredicateExpander::expandCheckOpcode()`. +// +// New MCInstPredicate classes must be added to this file. For each new class +// XYZ, an "expandXYZ" method must be added to the PredicateExpander. +// +//===----------------------------------------------------------------------===// + +// Forward declarations. +class Instruction; + +// A generic machine instruction predicate. +class MCInstPredicate; + +class MCTrue : MCInstPredicate; // A predicate that always evaluates to True. +class MCFalse : MCInstPredicate; // A predicate that always evaluates to False. +def TruePred : MCTrue; +def FalsePred : MCFalse; + +// A predicate used to negate the outcome of another predicate. +// It allows to easily express "set difference" operations. For example, it +// makes it easy to describe a check that tests if an opcode is not part of a +// set of opcodes. +class CheckNot<MCInstPredicate P> : MCInstPredicate { + MCInstPredicate Pred = P; +} + +// This class is used as a building block to define predicates on instruction +// operands. It is used to reference a specific machine operand. +class MCOperandPredicate<int Index> : MCInstPredicate { + int OpIndex = Index; +} + +// Return true if machine operand at position `Index` is a register operand. +class CheckIsRegOperand<int Index> : MCOperandPredicate<Index>; + +// Return true if machine operand at position `Index` is an immediate operand. +class CheckIsImmOperand<int Index> : MCOperandPredicate<Index>; + +// Check if machine operands at index `First` and index `Second` both reference +// the same register. +class CheckSameRegOperand<int First, int Second> : MCInstPredicate { + int FirstIndex = First; + int SecondIndex = Second; +} + +// Check that the machine register operand at position `Index` references +// register R. This predicate assumes that we already checked that the machine +// operand at position `Index` is a register operand. +class CheckRegOperand<int Index, Register R> : MCOperandPredicate<Index> { + Register Reg = R; +} + +// Check if register operand at index `Index` is the invalid register. +class CheckInvalidRegOperand<int Index> : MCOperandPredicate<Index>; + +// Check that the operand at position `Index` is immediate `Imm`. +class CheckImmOperand<int Index, int Imm> : MCOperandPredicate<Index> { + int ImmVal = Imm; +} + +// Similar to CheckImmOperand, however the immediate is not a literal number. +// This is useful when we want to compare the value of an operand against an +// enum value, and we know the actual integer value of that enum. +class CheckImmOperand_s<int Index, string Value> : MCOperandPredicate<Index> { + string ImmVal = Value; +} + +// Check that the operand at position `Index` is immediate value zero. +class CheckZeroOperand<int Index> : CheckImmOperand<Index, 0>; + +// Check that the instruction has exactly `Num` operands. +class CheckNumOperands<int Num> : MCInstPredicate { + int NumOps = Num; +} + +// Check that the instruction opcode is one of the opcodes in set `Opcodes`. +// This is a simple set membership query. The easier way to check if an opcode +// is not a member of the set is by using a `CheckNot<CheckOpcode<[...]>>` +// sequence. +class CheckOpcode<list<Instruction> Opcodes> : MCInstPredicate { + list<Instruction> ValidOpcodes = Opcodes; +} + +// Check that the instruction opcode is a pseudo opcode member of the set +// `Opcodes`. This check is always expanded to "false" if we are generating +// code for MCInst. +class CheckPseudo<list<Instruction> Opcodes> : CheckOpcode<Opcodes>; + +// A non-portable predicate. Only to use as a last resort when a block of code +// cannot possibly be converted in a declarative way using other MCInstPredicate +// classes. This check is always expanded to "false" when generating code for +// MCInst. +class CheckNonPortable<string Code> : MCInstPredicate { + string CodeBlock = Code; +} + +// A sequence of predicates. It is used as the base class for CheckAll, and +// CheckAny. It allows to describe compositions of predicates. +class CheckPredicateSequence<list<MCInstPredicate> Preds> : MCInstPredicate { + list<MCInstPredicate> Predicates = Preds; +} + +// Check that all of the predicates in `Preds` evaluate to true. +class CheckAll<list<MCInstPredicate> Sequence> + : CheckPredicateSequence<Sequence>; + +// Check that at least one of the predicates in `Preds` evaluates to true. +class CheckAny<list<MCInstPredicate> Sequence> + : CheckPredicateSequence<Sequence>; + +// Check that a call to method `Name` in class "XXXGenInstrInfo" (where XXX is +// the `Target` name) returns true. +// +// TIIPredicate definitions are used to model calls to the target-specific +// InstrInfo. A TIIPredicate is treated specially by the InstrInfoEmitter +// tablegen backend, which will use it to automatically generate a definition in +// the target specific `GenInstrInfo` class. +class TIIPredicate<string Target, string Name, MCInstPredicate P> : MCInstPredicate { + string TargetName = Target; + string FunctionName = Name; + MCInstPredicate Pred = P; +} + +// A function predicate that takes as input a machine instruction, and returns +// a boolean value. +// +// This predicate is expanded into a function call by the PredicateExpander. +// In particular, the PredicateExpander would either expand this predicate into +// a call to `MCInstFn`, or into a call to`MachineInstrFn` depending on whether +// it is lowering predicates for MCInst or MachineInstr. +// +// In this context, `MCInstFn` and `MachineInstrFn` are both function names. +class CheckFunctionPredicate<string MCInstFn, string MachineInstrFn> : MCInstPredicate { + string MCInstFnName = MCInstFn; + string MachineInstrFnName = MachineInstrFn; +} diff --git a/capstone/suite/synctools/tablegen/include/llvm/Target/TargetItinerary.td b/capstone/suite/synctools/tablegen/include/llvm/Target/TargetItinerary.td new file mode 100644 index 000000000..182054d84 --- /dev/null +++ b/capstone/suite/synctools/tablegen/include/llvm/Target/TargetItinerary.td @@ -0,0 +1,152 @@ +//===- TargetItinerary.td - Target Itinierary Description --*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the target-independent scheduling interfaces +// which should be implemented by each target that uses instruction +// itineraries for scheduling. Itineraries are details reservation +// tables for each instruction class. They are most appropriate for +// in-order machine with complicated scheduling or bundling constraints. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Processor functional unit - These values represent the function units +// available across all chip sets for the target. Eg., IntUnit, FPUnit, ... +// These may be independent values for each chip set or may be shared across +// all chip sets of the target. Each functional unit is treated as a resource +// during scheduling and has an affect instruction order based on availability +// during a time interval. +// +class FuncUnit; + +//===----------------------------------------------------------------------===// +// Pipeline bypass / forwarding - These values specifies the symbolic names of +// pipeline bypasses which can be used to forward results of instructions +// that are forwarded to uses. +class Bypass; +def NoBypass : Bypass; + +class ReservationKind<bits<1> val> { + int Value = val; +} + +def Required : ReservationKind<0>; +def Reserved : ReservationKind<1>; + +//===----------------------------------------------------------------------===// +// Instruction stage - These values represent a non-pipelined step in +// the execution of an instruction. Cycles represents the number of +// discrete time slots needed to complete the stage. Units represent +// the choice of functional units that can be used to complete the +// stage. Eg. IntUnit1, IntUnit2. TimeInc indicates how many cycles +// should elapse from the start of this stage to the start of the next +// stage in the itinerary. For example: +// +// A stage is specified in one of two ways: +// +// InstrStage<1, [FU_x, FU_y]> - TimeInc defaults to Cycles +// InstrStage<1, [FU_x, FU_y], 0> - TimeInc explicit +// + +class InstrStage<int cycles, list<FuncUnit> units, + int timeinc = -1, + ReservationKind kind = Required> { + int Cycles = cycles; // length of stage in machine cycles + list<FuncUnit> Units = units; // choice of functional units + int TimeInc = timeinc; // cycles till start of next stage + int Kind = kind.Value; // kind of FU reservation +} + +//===----------------------------------------------------------------------===// +// Instruction itinerary - An itinerary represents a sequential series of steps +// required to complete an instruction. Itineraries are represented as lists of +// instruction stages. +// + +//===----------------------------------------------------------------------===// +// Instruction itinerary classes - These values represent 'named' instruction +// itinerary. Using named itineraries simplifies managing groups of +// instructions across chip sets. An instruction uses the same itinerary class +// across all chip sets. Thus a new chip set can be added without modifying +// instruction information. +// +class InstrItinClass; +def NoItinerary : InstrItinClass; + +//===----------------------------------------------------------------------===// +// Instruction itinerary data - These values provide a runtime map of an +// instruction itinerary class (name) to its itinerary data. +// +// NumMicroOps represents the number of micro-operations that each instruction +// in the class are decoded to. If the number is zero, then it means the +// instruction can decode into variable number of micro-ops and it must be +// determined dynamically. This directly relates to the itineraries +// global IssueWidth property, which constrains the number of microops +// that can issue per cycle. +// +// OperandCycles are optional "cycle counts". They specify the cycle after +// instruction issue the values which correspond to specific operand indices +// are defined or read. Bypasses are optional "pipeline forwarding paths", if +// a def by an instruction is available on a specific bypass and the use can +// read from the same bypass, then the operand use latency is reduced by one. +// +// InstrItinData<IIC_iLoad_i , [InstrStage<1, [A9_Pipe1]>, +// InstrStage<1, [A9_AGU]>], +// [3, 1], [A9_LdBypass]>, +// InstrItinData<IIC_iMVNr , [InstrStage<1, [A9_Pipe0, A9_Pipe1]>], +// [1, 1], [NoBypass, A9_LdBypass]>, +// +// In this example, the instruction of IIC_iLoadi reads its input on cycle 1 +// (after issue) and the result of the load is available on cycle 3. The result +// is available via forwarding path A9_LdBypass. If it's used by the first +// source operand of instructions of IIC_iMVNr class, then the operand latency +// is reduced by 1. +class InstrItinData<InstrItinClass Class, list<InstrStage> stages, + list<int> operandcycles = [], + list<Bypass> bypasses = [], int uops = 1> { + InstrItinClass TheClass = Class; + int NumMicroOps = uops; + list<InstrStage> Stages = stages; + list<int> OperandCycles = operandcycles; + list<Bypass> Bypasses = bypasses; +} + +//===----------------------------------------------------------------------===// +// Processor itineraries - These values represent the set of all itinerary +// classes for a given chip set. +// +// Set property values to -1 to use the default. +// See InstrItineraryProps for comments and defaults. +class ProcessorItineraries<list<FuncUnit> fu, list<Bypass> bp, + list<InstrItinData> iid> { + list<FuncUnit> FU = fu; + list<Bypass> BP = bp; + list<InstrItinData> IID = iid; +} + +// NoItineraries - A marker that can be used by processors without schedule +// info. Subtargets using NoItineraries can bypass the scheduler's +// expensive HazardRecognizer because no reservation table is needed. +def NoItineraries : ProcessorItineraries<[], [], []>; + +//===----------------------------------------------------------------------===// +// Combo Function Unit data - This is a map of combo function unit names to +// the list of functional units that are included in the combination. +// +class ComboFuncData<FuncUnit ComboFunc, list<FuncUnit> funclist> { + FuncUnit TheComboFunc = ComboFunc; + list<FuncUnit> FuncList = funclist; +} + +//===----------------------------------------------------------------------===// +// Combo Function Units - This is a list of all combo function unit data. +class ComboFuncUnits<list<ComboFuncData> cfd> { + list<ComboFuncData> CFD = cfd; +} + diff --git a/capstone/suite/synctools/tablegen/include/llvm/Target/TargetSchedule.td b/capstone/suite/synctools/tablegen/include/llvm/Target/TargetSchedule.td new file mode 100644 index 000000000..6fd2d5b78 --- /dev/null +++ b/capstone/suite/synctools/tablegen/include/llvm/Target/TargetSchedule.td @@ -0,0 +1,553 @@ +//===- TargetSchedule.td - Target Independent Scheduling ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the target-independent scheduling interfaces which should +// be implemented by each target which is using TableGen based scheduling. +// +// The SchedMachineModel is defined by subtargets for three categories of data: +// 1. Basic properties for coarse grained instruction cost model. +// 2. Scheduler Read/Write resources for simple per-opcode cost model. +// 3. Instruction itineraries for detailed reservation tables. +// +// (1) Basic properties are defined by the SchedMachineModel +// class. Target hooks allow subtargets to associate opcodes with +// those properties. +// +// (2) A per-operand machine model can be implemented in any +// combination of the following ways: +// +// A. Associate per-operand SchedReadWrite types with Instructions by +// modifying the Instruction definition to inherit from Sched. For +// each subtarget, define WriteRes and ReadAdvance to associate +// processor resources and latency with each SchedReadWrite type. +// +// B. In each instruction definition, name an ItineraryClass. For each +// subtarget, define ItinRW entries to map ItineraryClass to +// per-operand SchedReadWrite types. Unlike method A, these types may +// be subtarget specific and can be directly associated with resources +// by defining SchedWriteRes and SchedReadAdvance. +// +// C. In the subtarget, map SchedReadWrite types to specific +// opcodes. This overrides any SchedReadWrite types or +// ItineraryClasses defined by the Instruction. As in method B, the +// subtarget can directly associate resources with SchedReadWrite +// types by defining SchedWriteRes and SchedReadAdvance. +// +// D. In either the target or subtarget, define SchedWriteVariant or +// SchedReadVariant to map one SchedReadWrite type onto another +// sequence of SchedReadWrite types. This allows dynamic selection of +// an instruction's machine model via custom C++ code. It also allows +// a machine-independent SchedReadWrite type to map to a sequence of +// machine-dependent types. +// +// (3) A per-pipeline-stage machine model can be implemented by providing +// Itineraries in addition to mapping instructions to ItineraryClasses. +//===----------------------------------------------------------------------===// + +// Include legacy support for instruction itineraries. +include "llvm/Target/TargetItinerary.td" + +class Instruction; // Forward def + +class Predicate; // Forward def + +// DAG operator that interprets the DAG args as Instruction defs. +def instrs; + +// DAG operator that interprets each DAG arg as a regex pattern for +// matching Instruction opcode names. +// The regex must match the beginning of the opcode (as in Python re.match). +// To avoid matching prefixes, append '$' to the pattern. +def instregex; + +// Define the SchedMachineModel and provide basic properties for +// coarse grained instruction cost model. Default values for the +// properties are defined in MCSchedModel. A value of "-1" in the +// target description's SchedMachineModel indicates that the property +// is not overriden by the target. +// +// Target hooks allow subtargets to associate LoadLatency and +// HighLatency with groups of opcodes. +// +// See MCSchedule.h for detailed comments. +class SchedMachineModel { + int IssueWidth = -1; // Max micro-ops that may be scheduled per cycle. + int MicroOpBufferSize = -1; // Max micro-ops that can be buffered. + int LoopMicroOpBufferSize = -1; // Max micro-ops that can be buffered for + // optimized loop dispatch/execution. + int LoadLatency = -1; // Cycles for loads to access the cache. + int HighLatency = -1; // Approximation of cycles for "high latency" ops. + int MispredictPenalty = -1; // Extra cycles for a mispredicted branch. + + // Per-cycle resources tables. + ProcessorItineraries Itineraries = NoItineraries; + + bit PostRAScheduler = 0; // Enable Post RegAlloc Scheduler pass. + + // Subtargets that define a model for only a subset of instructions + // that have a scheduling class (itinerary class or SchedRW list) + // and may actually be generated for that subtarget must clear this + // bit. Otherwise, the scheduler considers an unmodelled opcode to + // be an error. This should only be set during initial bringup, + // or there will be no way to catch simple errors in the model + // resulting from changes to the instruction definitions. + bit CompleteModel = 1; + + // Indicates that we should do full overlap checking for multiple InstrRWs + // definining the same instructions within the same SchedMachineModel. + // FIXME: Remove when all in tree targets are clean with the full check + // enabled. + bit FullInstRWOverlapCheck = 1; + + // A processor may only implement part of published ISA, due to either new ISA + // extensions, (e.g. Pentium 4 doesn't have AVX) or implementation + // (ARM/MIPS/PowerPC/SPARC soft float cores). + // + // For a processor which doesn't support some feature(s), the schedule model + // can use: + // + // let<Predicate> UnsupportedFeatures = [HaveA,..,HaveY]; + // + // to skip the checks for scheduling information when building LLVM for + // instructions which have any of the listed predicates in their Predicates + // field. + list<Predicate> UnsupportedFeatures = []; + + bit NoModel = 0; // Special tag to indicate missing machine model. +} + +def NoSchedModel : SchedMachineModel { + let NoModel = 1; + let CompleteModel = 0; +} + +// Define a kind of processor resource that may be common across +// similar subtargets. +class ProcResourceKind; + +// Define a number of interchangeable processor resources. NumUnits +// determines the throughput of instructions that require the resource. +// +// An optional Super resource may be given to model these resources as +// a subset of the more general super resources. Using one of these +// resources implies using one of the super resoruces. +// +// ProcResourceUnits normally model a few buffered resources within an +// out-of-order engine. Buffered resources may be held for multiple +// clock cycles, but the scheduler does not pin them to a particular +// clock cycle relative to instruction dispatch. Setting BufferSize=0 +// changes this to an in-order issue/dispatch resource. In this case, +// the scheduler counts down from the cycle that the instruction +// issues in-order, forcing a stall whenever a subsequent instruction +// requires the same resource until the number of ResourceCycles +// specified in WriteRes expire. Setting BufferSize=1 changes this to +// an in-order latency resource. In this case, the scheduler models +// producer/consumer stalls between instructions that use the +// resource. +// +// Examples (all assume an out-of-order engine): +// +// Use BufferSize = -1 for "issue ports" fed by a unified reservation +// station. Here the size of the reservation station is modeled by +// MicroOpBufferSize, which should be the minimum size of either the +// register rename pool, unified reservation station, or reorder +// buffer. +// +// Use BufferSize = 0 for resources that force "dispatch/issue +// groups". (Different processors define dispath/issue +// differently. Here we refer to stage between decoding into micro-ops +// and moving them into a reservation station.) Normally NumMicroOps +// is sufficient to limit dispatch/issue groups. However, some +// processors can form groups of with only certain combinitions of +// instruction types. e.g. POWER7. +// +// Use BufferSize = 1 for in-order execution units. This is used for +// an in-order pipeline within an out-of-order core where scheduling +// dependent operations back-to-back is guaranteed to cause a +// bubble. e.g. Cortex-a9 floating-point. +// +// Use BufferSize > 1 for out-of-order executions units with a +// separate reservation station. This simply models the size of the +// reservation station. +// +// To model both dispatch/issue groups and in-order execution units, +// create two types of units, one with BufferSize=0 and one with +// BufferSize=1. +// +// SchedModel ties these units to a processor for any stand-alone defs +// of this class. +class ProcResourceUnits<ProcResourceKind kind, int num, + list<string> pfmCounters> { + ProcResourceKind Kind = kind; + int NumUnits = num; + ProcResourceKind Super = ?; + int BufferSize = -1; + SchedMachineModel SchedModel = ?; +} + +// EponymousProcResourceKind helps implement ProcResourceUnits by +// allowing a ProcResourceUnits definition to reference itself. It +// should not be referenced anywhere else. +def EponymousProcResourceKind : ProcResourceKind; + +// Subtargets typically define processor resource kind and number of +// units in one place. +class ProcResource<int num, list<string> pfmCounters = []> : ProcResourceKind, + ProcResourceUnits<EponymousProcResourceKind, num, pfmCounters>; + +class ProcResGroup<list<ProcResource> resources> : ProcResourceKind { + list<ProcResource> Resources = resources; + SchedMachineModel SchedModel = ?; + int BufferSize = -1; +} + +// A target architecture may define SchedReadWrite types and associate +// them with instruction operands. +class SchedReadWrite; + +// List the per-operand types that map to the machine model of an +// instruction. One SchedWrite type must be listed for each explicit +// def operand in order. Additional SchedWrite types may optionally be +// listed for implicit def operands. SchedRead types may optionally +// be listed for use operands in order. The order of defs relative to +// uses is insignificant. This way, the same SchedReadWrite list may +// be used for multiple forms of an operation. For example, a +// two-address instruction could have two tied operands or single +// operand that both reads and writes a reg. In both cases we have a +// single SchedWrite and single SchedRead in any order. +class Sched<list<SchedReadWrite> schedrw> { + list<SchedReadWrite> SchedRW = schedrw; +} + +// Define a scheduler resource associated with a def operand. +class SchedWrite : SchedReadWrite; +def NoWrite : SchedWrite; + +// Define a scheduler resource associated with a use operand. +class SchedRead : SchedReadWrite; + +// Define a SchedWrite that is modeled as a sequence of other +// SchedWrites with additive latency. This allows a single operand to +// be mapped the resources composed from a set of previously defined +// SchedWrites. +// +// If the final write in this sequence is a SchedWriteVariant marked +// Variadic, then the list of prior writes are distributed across all +// operands after resolving the predicate for the final write. +// +// SchedModel silences warnings but is ignored. +class WriteSequence<list<SchedWrite> writes, int rep = 1> : SchedWrite { + list<SchedWrite> Writes = writes; + int Repeat = rep; + SchedMachineModel SchedModel = ?; +} + +// Define values common to WriteRes and SchedWriteRes. +// +// SchedModel ties these resources to a processor. +class ProcWriteResources<list<ProcResourceKind> resources> { + list<ProcResourceKind> ProcResources = resources; + list<int> ResourceCycles = []; + int Latency = 1; + int NumMicroOps = 1; + bit BeginGroup = 0; + bit EndGroup = 0; + // Allow a processor to mark some scheduling classes as unsupported + // for stronger verification. + bit Unsupported = 0; + // Allow a processor to mark some scheduling classes as single-issue. + // SingleIssue is an alias for Begin/End Group. + bit SingleIssue = 0; + SchedMachineModel SchedModel = ?; +} + +// Define the resources and latency of a SchedWrite. This will be used +// directly by targets that have no itinerary classes. In this case, +// SchedWrite is defined by the target, while WriteResources is +// defined by the subtarget, and maps the SchedWrite to processor +// resources. +// +// If a target already has itinerary classes, SchedWriteResources can +// be used instead to define subtarget specific SchedWrites and map +// them to processor resources in one place. Then ItinRW can map +// itinerary classes to the subtarget's SchedWrites. +// +// ProcResources indicates the set of resources consumed by the write. +// Optionally, ResourceCycles indicates the number of cycles the +// resource is consumed. Each ResourceCycles item is paired with the +// ProcResource item at the same position in its list. ResourceCycles +// can be `[]`: in that case, all resources are consumed for a single +// cycle, regardless of latency, which models a fully pipelined processing +// unit. A value of 0 for ResourceCycles means that the resource must +// be available but is not consumed, which is only relevant for +// unbuffered resources. +// +// By default, each SchedWrite takes one micro-op, which is counted +// against the processor's IssueWidth limit. If an instruction can +// write multiple registers with a single micro-op, the subtarget +// should define one of the writes to be zero micro-ops. If a +// subtarget requires multiple micro-ops to write a single result, it +// should either override the write's NumMicroOps to be greater than 1 +// or require additional writes. Extra writes can be required either +// by defining a WriteSequence, or simply listing extra writes in the +// instruction's list of writers beyond the number of "def" +// operands. The scheduler assumes that all micro-ops must be +// dispatched in the same cycle. These micro-ops may be required to +// begin or end the current dispatch group. +class WriteRes<SchedWrite write, list<ProcResourceKind> resources> + : ProcWriteResources<resources> { + SchedWrite WriteType = write; +} + +// Directly name a set of WriteResources defining a new SchedWrite +// type at the same time. This class is unaware of its SchedModel so +// must be referenced by InstRW or ItinRW. +class SchedWriteRes<list<ProcResourceKind> resources> : SchedWrite, + ProcWriteResources<resources>; + +// Define values common to ReadAdvance and SchedReadAdvance. +// +// SchedModel ties these resources to a processor. +class ProcReadAdvance<int cycles, list<SchedWrite> writes = []> { + int Cycles = cycles; + list<SchedWrite> ValidWrites = writes; + // Allow a processor to mark some scheduling classes as unsupported + // for stronger verification. + bit Unsupported = 0; + SchedMachineModel SchedModel = ?; +} + +// A processor may define a ReadAdvance associated with a SchedRead +// to reduce latency of a prior write by N cycles. A negative advance +// effectively increases latency, which may be used for cross-domain +// stalls. +// +// A ReadAdvance may be associated with a list of SchedWrites +// to implement pipeline bypass. The Writes list may be empty to +// indicate operands that are always read this number of Cycles later +// than a normal register read, allowing the read's parent instruction +// to issue earlier relative to the writer. +class ReadAdvance<SchedRead read, int cycles, list<SchedWrite> writes = []> + : ProcReadAdvance<cycles, writes> { + SchedRead ReadType = read; +} + +// Directly associate a new SchedRead type with a delay and optional +// pipeline bypass. For use with InstRW or ItinRW. +class SchedReadAdvance<int cycles, list<SchedWrite> writes = []> : SchedRead, + ProcReadAdvance<cycles, writes>; + +// Define SchedRead defaults. Reads seldom need special treatment. +def ReadDefault : SchedRead; +def NoReadAdvance : SchedReadAdvance<0>; + +// Define shared code that will be in the same scope as all +// SchedPredicates. Available variables are: +// (const MachineInstr *MI, const TargetSchedModel *SchedModel) +class PredicateProlog<code c> { + code Code = c; +} + +// Base class for scheduling predicates. +class SchedPredicateBase; + +// A scheduling predicate whose logic is defined by a MCInstPredicate. +// This can directly be used by SchedWriteVariant definitions. +class MCSchedPredicate<MCInstPredicate P> : SchedPredicateBase { + MCInstPredicate Pred = P; + SchedMachineModel SchedModel = ?; +} + +// Define a predicate to determine which SchedVariant applies to a +// particular MachineInstr. The code snippet is used as an +// if-statement's expression. Available variables are MI, SchedModel, +// and anything defined in a PredicateProlog. +// +// SchedModel silences warnings but is ignored. +class SchedPredicate<code pred> : SchedPredicateBase { + SchedMachineModel SchedModel = ?; + code Predicate = pred; +} +def NoSchedPred : SchedPredicate<[{true}]>; + +// Associate a predicate with a list of SchedReadWrites. By default, +// the selected SchedReadWrites are still associated with a single +// operand and assumed to execute sequentially with additive +// latency. However, if the parent SchedWriteVariant or +// SchedReadVariant is marked "Variadic", then each Selected +// SchedReadWrite is mapped in place to the instruction's variadic +// operands. In this case, latency is not additive. If the current Variant +// is already part of a Sequence, then that entire chain leading up to +// the Variant is distributed over the variadic operands. +class SchedVar<SchedPredicateBase pred, list<SchedReadWrite> selected> { + SchedPredicateBase Predicate = pred; + list<SchedReadWrite> Selected = selected; +} + +// SchedModel silences warnings but is ignored. +class SchedVariant<list<SchedVar> variants> { + list<SchedVar> Variants = variants; + bit Variadic = 0; + SchedMachineModel SchedModel = ?; +} + +// A SchedWriteVariant is a single SchedWrite type that maps to a list +// of SchedWrite types under the conditions defined by its predicates. +// +// A Variadic write is expanded to cover multiple "def" operands. The +// SchedVariant's Expansion list is then interpreted as one write +// per-operand instead of the usual sequential writes feeding a single +// operand. +class SchedWriteVariant<list<SchedVar> variants> : SchedWrite, + SchedVariant<variants> { +} + +// A SchedReadVariant is a single SchedRead type that maps to a list +// of SchedRead types under the conditions defined by its predicates. +// +// A Variadic write is expanded to cover multiple "readsReg" operands as +// explained above. +class SchedReadVariant<list<SchedVar> variants> : SchedRead, + SchedVariant<variants> { +} + +// Map a set of opcodes to a list of SchedReadWrite types. This allows +// the subtarget to easily override specific operations. +// +// SchedModel ties this opcode mapping to a processor. +class InstRW<list<SchedReadWrite> rw, dag instrlist> { + list<SchedReadWrite> OperandReadWrites = rw; + dag Instrs = instrlist; + SchedMachineModel SchedModel = ?; + // Allow a subtarget to mark some instructions as unsupported. + bit Unsupported = 0; +} + +// Map a set of itinerary classes to SchedReadWrite resources. This is +// used to bootstrap a target (e.g. ARM) when itineraries already +// exist and changing InstrInfo is undesirable. +// +// SchedModel ties this ItineraryClass mapping to a processor. +class ItinRW<list<SchedReadWrite> rw, list<InstrItinClass> iic> { + list<InstrItinClass> MatchedItinClasses = iic; + list<SchedReadWrite> OperandReadWrites = rw; + SchedMachineModel SchedModel = ?; +} + +// Alias a target-defined SchedReadWrite to a processor specific +// SchedReadWrite. This allows a subtarget to easily map a +// SchedReadWrite type onto a WriteSequence, SchedWriteVariant, or +// SchedReadVariant. +// +// SchedModel will usually be provided by surrounding let statement +// and ties this SchedAlias mapping to a processor. +class SchedAlias<SchedReadWrite match, SchedReadWrite alias> { + SchedReadWrite MatchRW = match; + SchedReadWrite AliasRW = alias; + SchedMachineModel SchedModel = ?; +} + +// Allow the definition of processor register files for register renaming +// purposes. +// +// Each processor register file declares: +// - The set of registers that can be renamed. +// - The number of physical registers which can be used for register renaming +// purpose. +// - The cost of a register rename. +// +// The cost of a rename is the number of physical registers allocated by the +// register alias table to map the new definition. By default, register can be +// renamed at the cost of a single physical register. Note that register costs +// are defined at register class granularity (see field `Costs`). +// +// The set of registers that are subject to register renaming is declared using +// a list of register classes (see field `RegClasses`). An empty list of +// register classes means: all the logical registers defined by the target can +// be fully renamed. +// +// A register R can be renamed if its register class appears in the `RegClasses` +// set. When R is written, a new alias is allocated at the cost of one or more +// physical registers; as a result, false dependencies on R are removed. +// +// A sub-register V of register R is implicitly part of the same register file. +// However, V is only renamed if its register class is part of `RegClasses`. +// Otherwise, the processor keeps it (as well as any other different part +// of R) together with R, and a write of V always causes a compulsory read of R. +// +// This is what happens for example on AMD processors (at least from Bulldozer +// onwards), where AL and AH are not treated as independent from AX, and AX is +// not treated as independent from EAX. A write to AL has an implicity false +// dependency on the last write to EAX (or a portion of EAX). As a consequence, +// a write to AL cannot go in parallel with a write to AH. +// +// There is no false dependency if the partial register write belongs to a +// register class that is in `RegClasses`. +// There is also no penalty for writes that "clear the content a super-register" +// (see MC/MCInstrAnalysis.h - method MCInstrAnalysis::clearsSuperRegisters()). +// On x86-64, 32-bit GPR writes implicitly zero the upper half of the underlying +// physical register, effectively removing any false dependencies with the +// previous register definition. +// +// TODO: This implementation assumes that there is no limit in the number of +// renames per cycle, which might not be true for all hardware or register +// classes. Also, there is no limit to how many times the same logical register +// can be renamed during the same cycle. +// +// TODO: we don't currently model merge penalties for the case where a write to +// a part of a register is followed by a read from a larger part of the same +// register. On some Intel chips, different parts of a GPR can be stored in +// different physical registers. However, there is a cost to pay for when the +// partial write is combined with the previous super-register definition. We +// should add support for these cases, and correctly model merge problems with +// partial register accesses. +class RegisterFile<int numPhysRegs, list<RegisterClass> Classes = [], + list<int> Costs = []> { + list<RegisterClass> RegClasses = Classes; + list<int> RegCosts = Costs; + int NumPhysRegs = numPhysRegs; + SchedMachineModel SchedModel = ?; +} + +// Describe the retire control unit. +// A retire control unit specifies the size of the reorder buffer, as well as +// the maximum number of opcodes that can be retired every cycle. +// A value less-than-or-equal-to zero for field 'ReorderBufferSize' means: "the +// size is unknown". The idea is that external tools can fall-back to using +// field MicroOpBufferSize in SchedModel if the reorder buffer size is unknown. +// A zero or negative value for field 'MaxRetirePerCycle' means "no +// restrictions on the number of instructions retired per cycle". +// Models can optionally specify up to one instance of RetireControlUnit per +// scheduling model. +class RetireControlUnit<int bufferSize, int retirePerCycle> { + int ReorderBufferSize = bufferSize; + int MaxRetirePerCycle = retirePerCycle; + SchedMachineModel SchedModel = ?; +} + +// Allow the definition of hardware counters. +class PfmCounter { + SchedMachineModel SchedModel = ?; +} + +// Each processor can define how to measure cycles by defining a +// PfmCycleCounter. +class PfmCycleCounter<string counter> : PfmCounter { + string Counter = counter; +} + +// Each ProcResourceUnits can define how to measure issued uops by defining +// a PfmIssueCounter. +class PfmIssueCounter<ProcResourceUnits resource, list<string> counters> + : PfmCounter{ + // The resource units on which uops are issued. + ProcResourceUnits Resource = resource; + // The list of counters that measure issue events. + list<string> Counters = counters; +} diff --git a/capstone/suite/synctools/tablegen/include/llvm/Target/TargetSelectionDAG.td b/capstone/suite/synctools/tablegen/include/llvm/Target/TargetSelectionDAG.td new file mode 100644 index 000000000..4ba4d8212 --- /dev/null +++ b/capstone/suite/synctools/tablegen/include/llvm/Target/TargetSelectionDAG.td @@ -0,0 +1,1335 @@ +//===- TargetSelectionDAG.td - Common code for DAG isels ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the target-independent interfaces used by SelectionDAG +// instruction selection generators. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Selection DAG Type Constraint definitions. +// +// Note that the semantics of these constraints are hard coded into tblgen. To +// modify or add constraints, you have to hack tblgen. +// + +class SDTypeConstraint<int opnum> { + int OperandNum = opnum; +} + +// SDTCisVT - The specified operand has exactly this VT. +class SDTCisVT<int OpNum, ValueType vt> : SDTypeConstraint<OpNum> { + ValueType VT = vt; +} + +class SDTCisPtrTy<int OpNum> : SDTypeConstraint<OpNum>; + +// SDTCisInt - The specified operand has integer type. +class SDTCisInt<int OpNum> : SDTypeConstraint<OpNum>; + +// SDTCisFP - The specified operand has floating-point type. +class SDTCisFP<int OpNum> : SDTypeConstraint<OpNum>; + +// SDTCisVec - The specified operand has a vector type. +class SDTCisVec<int OpNum> : SDTypeConstraint<OpNum>; + +// SDTCisSameAs - The two specified operands have identical types. +class SDTCisSameAs<int OpNum, int OtherOp> : SDTypeConstraint<OpNum> { + int OtherOperandNum = OtherOp; +} + +// SDTCisVTSmallerThanOp - The specified operand is a VT SDNode, and its type is +// smaller than the 'Other' operand. +class SDTCisVTSmallerThanOp<int OpNum, int OtherOp> : SDTypeConstraint<OpNum> { + int OtherOperandNum = OtherOp; +} + +class SDTCisOpSmallerThanOp<int SmallOp, int BigOp> : SDTypeConstraint<SmallOp>{ + int BigOperandNum = BigOp; +} + +/// SDTCisEltOfVec - This indicates that ThisOp is a scalar type of the same +/// type as the element type of OtherOp, which is a vector type. +class SDTCisEltOfVec<int ThisOp, int OtherOp> + : SDTypeConstraint<ThisOp> { + int OtherOpNum = OtherOp; +} + +/// SDTCisSubVecOfVec - This indicates that ThisOp is a vector type +/// with length less that of OtherOp, which is a vector type. +class SDTCisSubVecOfVec<int ThisOp, int OtherOp> + : SDTypeConstraint<ThisOp> { + int OtherOpNum = OtherOp; +} + +// SDTCVecEltisVT - The specified operand is vector type with element type +// of VT. +class SDTCVecEltisVT<int OpNum, ValueType vt> : SDTypeConstraint<OpNum> { + ValueType VT = vt; +} + +// SDTCisSameNumEltsAs - The two specified operands have identical number +// of elements. +class SDTCisSameNumEltsAs<int OpNum, int OtherOp> : SDTypeConstraint<OpNum> { + int OtherOperandNum = OtherOp; +} + +// SDTCisSameSizeAs - The two specified operands have identical size. +class SDTCisSameSizeAs<int OpNum, int OtherOp> : SDTypeConstraint<OpNum> { + int OtherOperandNum = OtherOp; +} + +//===----------------------------------------------------------------------===// +// Selection DAG Type Profile definitions. +// +// These use the constraints defined above to describe the type requirements of +// the various nodes. These are not hard coded into tblgen, allowing targets to +// add their own if needed. +// + +// SDTypeProfile - This profile describes the type requirements of a Selection +// DAG node. +class SDTypeProfile<int numresults, int numoperands, + list<SDTypeConstraint> constraints> { + int NumResults = numresults; + int NumOperands = numoperands; + list<SDTypeConstraint> Constraints = constraints; +} + +// Builtin profiles. +def SDTIntLeaf: SDTypeProfile<1, 0, [SDTCisInt<0>]>; // for 'imm'. +def SDTFPLeaf : SDTypeProfile<1, 0, [SDTCisFP<0>]>; // for 'fpimm'. +def SDTPtrLeaf: SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; // for '&g'. +def SDTOther : SDTypeProfile<1, 0, [SDTCisVT<0, OtherVT>]>; // for 'vt'. +def SDTUNDEF : SDTypeProfile<1, 0, []>; // for 'undef'. +def SDTUnaryOp : SDTypeProfile<1, 1, []>; // for bitconvert. + +def SDTIntBinOp : SDTypeProfile<1, 2, [ // add, and, or, xor, udiv, etc. + SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisInt<0> +]>; +def SDTIntShiftOp : SDTypeProfile<1, 2, [ // shl, sra, srl + SDTCisSameAs<0, 1>, SDTCisInt<0>, SDTCisInt<2> +]>; +def SDTIntSatNoShOp : SDTypeProfile<1, 2, [ // ssat with no shift + SDTCisSameAs<0, 1>, SDTCisInt<2> +]>; +def SDTIntBinHiLoOp : SDTypeProfile<2, 2, [ // mulhi, mullo, sdivrem, udivrem + SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>,SDTCisInt<0> +]>; + +def SDTFPBinOp : SDTypeProfile<1, 2, [ // fadd, fmul, etc. + SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisFP<0> +]>; +def SDTFPSignOp : SDTypeProfile<1, 2, [ // fcopysign. + SDTCisSameAs<0, 1>, SDTCisFP<0>, SDTCisFP<2> +]>; +def SDTFPTernaryOp : SDTypeProfile<1, 3, [ // fmadd, fnmsub, etc. + SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>, SDTCisFP<0> +]>; +def SDTIntUnaryOp : SDTypeProfile<1, 1, [ // ctlz, cttz + SDTCisSameAs<0, 1>, SDTCisInt<0> +]>; +def SDTIntExtendOp : SDTypeProfile<1, 1, [ // sext, zext, anyext + SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<1, 0>, SDTCisSameNumEltsAs<0, 1> +]>; +def SDTIntTruncOp : SDTypeProfile<1, 1, [ // trunc + SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<0, 1>, SDTCisSameNumEltsAs<0, 1> +]>; +def SDTFPUnaryOp : SDTypeProfile<1, 1, [ // fneg, fsqrt, etc + SDTCisSameAs<0, 1>, SDTCisFP<0> +]>; +def SDTFPRoundOp : SDTypeProfile<1, 1, [ // fround + SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<0, 1>, SDTCisSameNumEltsAs<0, 1> +]>; +def SDTFPExtendOp : SDTypeProfile<1, 1, [ // fextend + SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<1, 0>, SDTCisSameNumEltsAs<0, 1> +]>; +def SDTIntToFPOp : SDTypeProfile<1, 1, [ // [su]int_to_fp + SDTCisFP<0>, SDTCisInt<1>, SDTCisSameNumEltsAs<0, 1> +]>; +def SDTFPToIntOp : SDTypeProfile<1, 1, [ // fp_to_[su]int + SDTCisInt<0>, SDTCisFP<1>, SDTCisSameNumEltsAs<0, 1> +]>; +def SDTExtInreg : SDTypeProfile<1, 2, [ // sext_inreg + SDTCisSameAs<0, 1>, SDTCisInt<0>, SDTCisVT<2, OtherVT>, + SDTCisVTSmallerThanOp<2, 1> +]>; +def SDTExtInvec : SDTypeProfile<1, 1, [ // sext_invec + SDTCisInt<0>, SDTCisVec<0>, SDTCisInt<1>, SDTCisVec<1>, + SDTCisOpSmallerThanOp<1, 0>, SDTCisSameSizeAs<0,1> +]>; + +def SDTSetCC : SDTypeProfile<1, 3, [ // setcc + SDTCisInt<0>, SDTCisSameAs<1, 2>, SDTCisVT<3, OtherVT> +]>; + +def SDTSelect : SDTypeProfile<1, 3, [ // select + SDTCisInt<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3> +]>; + +def SDTVSelect : SDTypeProfile<1, 3, [ // vselect + SDTCisVec<0>, SDTCisInt<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>, SDTCisSameNumEltsAs<0, 1> +]>; + +def SDTSelectCC : SDTypeProfile<1, 5, [ // select_cc + SDTCisSameAs<1, 2>, SDTCisSameAs<3, 4>, SDTCisSameAs<0, 3>, + SDTCisVT<5, OtherVT> +]>; + +def SDTBr : SDTypeProfile<0, 1, [ // br + SDTCisVT<0, OtherVT> +]>; + +def SDTBrCC : SDTypeProfile<0, 4, [ // brcc + SDTCisVT<0, OtherVT>, SDTCisSameAs<1, 2>, SDTCisVT<3, OtherVT> +]>; + +def SDTBrcond : SDTypeProfile<0, 2, [ // brcond + SDTCisInt<0>, SDTCisVT<1, OtherVT> +]>; + +def SDTBrind : SDTypeProfile<0, 1, [ // brind + SDTCisPtrTy<0> +]>; + +def SDTCatchret : SDTypeProfile<0, 2, [ // catchret + SDTCisVT<0, OtherVT>, SDTCisVT<1, OtherVT> +]>; + +def SDTNone : SDTypeProfile<0, 0, []>; // ret, trap + +def SDTLoad : SDTypeProfile<1, 1, [ // load + SDTCisPtrTy<1> +]>; + +def SDTStore : SDTypeProfile<0, 2, [ // store + SDTCisPtrTy<1> +]>; + +def SDTIStore : SDTypeProfile<1, 3, [ // indexed store + SDTCisSameAs<0, 2>, SDTCisPtrTy<0>, SDTCisPtrTy<3> +]>; + +def SDTMaskedStore: SDTypeProfile<0, 3, [ // masked store + SDTCisPtrTy<0>, SDTCisVec<1>, SDTCisVec<2>, SDTCisSameNumEltsAs<1, 2> +]>; + +def SDTMaskedLoad: SDTypeProfile<1, 3, [ // masked load + SDTCisVec<0>, SDTCisPtrTy<1>, SDTCisVec<2>, SDTCisSameAs<0, 3>, + SDTCisSameNumEltsAs<0, 2> +]>; + +def SDTMaskedGather: SDTypeProfile<2, 3, [ // masked gather + SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<1, 3>, + SDTCisPtrTy<4>, SDTCVecEltisVT<1, i1>, SDTCisSameNumEltsAs<0, 1> +]>; + +def SDTMaskedScatter: SDTypeProfile<1, 3, [ // masked scatter + SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<0, 2>, SDTCisSameNumEltsAs<0, 1>, + SDTCVecEltisVT<0, i1>, SDTCisPtrTy<3> +]>; + +def SDTVecShuffle : SDTypeProfile<1, 2, [ + SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2> +]>; +def SDTVecExtract : SDTypeProfile<1, 2, [ // vector extract + SDTCisEltOfVec<0, 1>, SDTCisPtrTy<2> +]>; +def SDTVecInsert : SDTypeProfile<1, 3, [ // vector insert + SDTCisEltOfVec<2, 1>, SDTCisSameAs<0, 1>, SDTCisPtrTy<3> +]>; + +def SDTSubVecExtract : SDTypeProfile<1, 2, [// subvector extract + SDTCisSubVecOfVec<0,1>, SDTCisInt<2> +]>; +def SDTSubVecInsert : SDTypeProfile<1, 3, [ // subvector insert + SDTCisSubVecOfVec<2, 1>, SDTCisSameAs<0,1>, SDTCisInt<3> +]>; + +def SDTPrefetch : SDTypeProfile<0, 4, [ // prefetch + SDTCisPtrTy<0>, SDTCisSameAs<1, 2>, SDTCisSameAs<1, 3>, SDTCisInt<1> +]>; + +def SDTMemBarrier : SDTypeProfile<0, 5, [ // memory barrier + SDTCisSameAs<0,1>, SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisSameAs<0,4>, + SDTCisInt<0> +]>; +def SDTAtomicFence : SDTypeProfile<0, 2, [ + SDTCisSameAs<0,1>, SDTCisPtrTy<0> +]>; +def SDTAtomic3 : SDTypeProfile<1, 3, [ + SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisInt<0>, SDTCisPtrTy<1> +]>; +def SDTAtomic2 : SDTypeProfile<1, 2, [ + SDTCisSameAs<0,2>, SDTCisInt<0>, SDTCisPtrTy<1> +]>; +def SDTAtomicStore : SDTypeProfile<0, 2, [ + SDTCisPtrTy<0>, SDTCisInt<1> +]>; +def SDTAtomicLoad : SDTypeProfile<1, 1, [ + SDTCisInt<0>, SDTCisPtrTy<1> +]>; + +def SDTConvertOp : SDTypeProfile<1, 5, [ //cvtss, su, us, uu, ff, fs, fu, sf, su + SDTCisVT<2, OtherVT>, SDTCisVT<3, OtherVT>, SDTCisPtrTy<4>, SDTCisPtrTy<5> +]>; + +class SDCallSeqStart<list<SDTypeConstraint> constraints> : + SDTypeProfile<0, 2, constraints>; +class SDCallSeqEnd<list<SDTypeConstraint> constraints> : + SDTypeProfile<0, 2, constraints>; + +//===----------------------------------------------------------------------===// +// Selection DAG Node definitions. +// +class SDNode<string opcode, SDTypeProfile typeprof, + list<SDNodeProperty> props = [], string sdclass = "SDNode"> + : SDPatternOperator { + string Opcode = opcode; + string SDClass = sdclass; + let Properties = props; + SDTypeProfile TypeProfile = typeprof; +} + +// Special TableGen-recognized dag nodes +def set; +def implicit; +def node; +def srcvalue; + +def imm : SDNode<"ISD::Constant" , SDTIntLeaf , [], "ConstantSDNode">; +def timm : SDNode<"ISD::TargetConstant",SDTIntLeaf, [], "ConstantSDNode">; +def fpimm : SDNode<"ISD::ConstantFP", SDTFPLeaf , [], "ConstantFPSDNode">; +def vt : SDNode<"ISD::VALUETYPE" , SDTOther , [], "VTSDNode">; +def bb : SDNode<"ISD::BasicBlock", SDTOther , [], "BasicBlockSDNode">; +def cond : SDNode<"ISD::CONDCODE" , SDTOther , [], "CondCodeSDNode">; +def undef : SDNode<"ISD::UNDEF" , SDTUNDEF , []>; +def globaladdr : SDNode<"ISD::GlobalAddress", SDTPtrLeaf, [], + "GlobalAddressSDNode">; +def tglobaladdr : SDNode<"ISD::TargetGlobalAddress", SDTPtrLeaf, [], + "GlobalAddressSDNode">; +def globaltlsaddr : SDNode<"ISD::GlobalTLSAddress", SDTPtrLeaf, [], + "GlobalAddressSDNode">; +def tglobaltlsaddr : SDNode<"ISD::TargetGlobalTLSAddress", SDTPtrLeaf, [], + "GlobalAddressSDNode">; +def constpool : SDNode<"ISD::ConstantPool", SDTPtrLeaf, [], + "ConstantPoolSDNode">; +def tconstpool : SDNode<"ISD::TargetConstantPool", SDTPtrLeaf, [], + "ConstantPoolSDNode">; +def jumptable : SDNode<"ISD::JumpTable", SDTPtrLeaf, [], + "JumpTableSDNode">; +def tjumptable : SDNode<"ISD::TargetJumpTable", SDTPtrLeaf, [], + "JumpTableSDNode">; +def frameindex : SDNode<"ISD::FrameIndex", SDTPtrLeaf, [], + "FrameIndexSDNode">; +def tframeindex : SDNode<"ISD::TargetFrameIndex", SDTPtrLeaf, [], + "FrameIndexSDNode">; +def externalsym : SDNode<"ISD::ExternalSymbol", SDTPtrLeaf, [], + "ExternalSymbolSDNode">; +def texternalsym: SDNode<"ISD::TargetExternalSymbol", SDTPtrLeaf, [], + "ExternalSymbolSDNode">; +def mcsym: SDNode<"ISD::MCSymbol", SDTPtrLeaf, [], "MCSymbolSDNode">; +def blockaddress : SDNode<"ISD::BlockAddress", SDTPtrLeaf, [], + "BlockAddressSDNode">; +def tblockaddress: SDNode<"ISD::TargetBlockAddress", SDTPtrLeaf, [], + "BlockAddressSDNode">; + +def add : SDNode<"ISD::ADD" , SDTIntBinOp , + [SDNPCommutative, SDNPAssociative]>; +def sub : SDNode<"ISD::SUB" , SDTIntBinOp>; +def mul : SDNode<"ISD::MUL" , SDTIntBinOp, + [SDNPCommutative, SDNPAssociative]>; +def mulhs : SDNode<"ISD::MULHS" , SDTIntBinOp, [SDNPCommutative]>; +def mulhu : SDNode<"ISD::MULHU" , SDTIntBinOp, [SDNPCommutative]>; +def smullohi : SDNode<"ISD::SMUL_LOHI" , SDTIntBinHiLoOp, [SDNPCommutative]>; +def umullohi : SDNode<"ISD::UMUL_LOHI" , SDTIntBinHiLoOp, [SDNPCommutative]>; +def sdiv : SDNode<"ISD::SDIV" , SDTIntBinOp>; +def udiv : SDNode<"ISD::UDIV" , SDTIntBinOp>; +def srem : SDNode<"ISD::SREM" , SDTIntBinOp>; +def urem : SDNode<"ISD::UREM" , SDTIntBinOp>; +def sdivrem : SDNode<"ISD::SDIVREM" , SDTIntBinHiLoOp>; +def udivrem : SDNode<"ISD::UDIVREM" , SDTIntBinHiLoOp>; +def srl : SDNode<"ISD::SRL" , SDTIntShiftOp>; +def sra : SDNode<"ISD::SRA" , SDTIntShiftOp>; +def shl : SDNode<"ISD::SHL" , SDTIntShiftOp>; +def rotl : SDNode<"ISD::ROTL" , SDTIntShiftOp>; +def rotr : SDNode<"ISD::ROTR" , SDTIntShiftOp>; +def and : SDNode<"ISD::AND" , SDTIntBinOp, + [SDNPCommutative, SDNPAssociative]>; +def or : SDNode<"ISD::OR" , SDTIntBinOp, + [SDNPCommutative, SDNPAssociative]>; +def xor : SDNode<"ISD::XOR" , SDTIntBinOp, + [SDNPCommutative, SDNPAssociative]>; +def addc : SDNode<"ISD::ADDC" , SDTIntBinOp, + [SDNPCommutative, SDNPOutGlue]>; +def adde : SDNode<"ISD::ADDE" , SDTIntBinOp, + [SDNPCommutative, SDNPOutGlue, SDNPInGlue]>; +def subc : SDNode<"ISD::SUBC" , SDTIntBinOp, + [SDNPOutGlue]>; +def sube : SDNode<"ISD::SUBE" , SDTIntBinOp, + [SDNPOutGlue, SDNPInGlue]>; +def smin : SDNode<"ISD::SMIN" , SDTIntBinOp, + [SDNPCommutative, SDNPAssociative]>; +def smax : SDNode<"ISD::SMAX" , SDTIntBinOp, + [SDNPCommutative, SDNPAssociative]>; +def umin : SDNode<"ISD::UMIN" , SDTIntBinOp, + [SDNPCommutative, SDNPAssociative]>; +def umax : SDNode<"ISD::UMAX" , SDTIntBinOp, + [SDNPCommutative, SDNPAssociative]>; + +def sext_inreg : SDNode<"ISD::SIGN_EXTEND_INREG", SDTExtInreg>; +def sext_invec : SDNode<"ISD::SIGN_EXTEND_VECTOR_INREG", SDTExtInvec>; +def zext_invec : SDNode<"ISD::ZERO_EXTEND_VECTOR_INREG", SDTExtInvec>; + +def abs : SDNode<"ISD::ABS" , SDTIntUnaryOp>; +def bitreverse : SDNode<"ISD::BITREVERSE" , SDTIntUnaryOp>; +def bswap : SDNode<"ISD::BSWAP" , SDTIntUnaryOp>; +def ctlz : SDNode<"ISD::CTLZ" , SDTIntUnaryOp>; +def cttz : SDNode<"ISD::CTTZ" , SDTIntUnaryOp>; +def ctpop : SDNode<"ISD::CTPOP" , SDTIntUnaryOp>; +def ctlz_zero_undef : SDNode<"ISD::CTLZ_ZERO_UNDEF", SDTIntUnaryOp>; +def cttz_zero_undef : SDNode<"ISD::CTTZ_ZERO_UNDEF", SDTIntUnaryOp>; +def sext : SDNode<"ISD::SIGN_EXTEND", SDTIntExtendOp>; +def zext : SDNode<"ISD::ZERO_EXTEND", SDTIntExtendOp>; +def anyext : SDNode<"ISD::ANY_EXTEND" , SDTIntExtendOp>; +def trunc : SDNode<"ISD::TRUNCATE" , SDTIntTruncOp>; +def bitconvert : SDNode<"ISD::BITCAST" , SDTUnaryOp>; +def addrspacecast : SDNode<"ISD::ADDRSPACECAST", SDTUnaryOp>; +def extractelt : SDNode<"ISD::EXTRACT_VECTOR_ELT", SDTVecExtract>; +def insertelt : SDNode<"ISD::INSERT_VECTOR_ELT", SDTVecInsert>; + +def fadd : SDNode<"ISD::FADD" , SDTFPBinOp, [SDNPCommutative]>; +def fsub : SDNode<"ISD::FSUB" , SDTFPBinOp>; +def fmul : SDNode<"ISD::FMUL" , SDTFPBinOp, [SDNPCommutative]>; +def fdiv : SDNode<"ISD::FDIV" , SDTFPBinOp>; +def frem : SDNode<"ISD::FREM" , SDTFPBinOp>; +def fma : SDNode<"ISD::FMA" , SDTFPTernaryOp>; +def fmad : SDNode<"ISD::FMAD" , SDTFPTernaryOp>; +def fabs : SDNode<"ISD::FABS" , SDTFPUnaryOp>; +def fminnum : SDNode<"ISD::FMINNUM" , SDTFPBinOp, + [SDNPCommutative, SDNPAssociative]>; +def fmaxnum : SDNode<"ISD::FMAXNUM" , SDTFPBinOp, + [SDNPCommutative, SDNPAssociative]>; +def fminnan : SDNode<"ISD::FMINNAN" , SDTFPBinOp>; +def fmaxnan : SDNode<"ISD::FMAXNAN" , SDTFPBinOp>; +def fgetsign : SDNode<"ISD::FGETSIGN" , SDTFPToIntOp>; +def fcanonicalize : SDNode<"ISD::FCANONICALIZE", SDTFPUnaryOp>; +def fneg : SDNode<"ISD::FNEG" , SDTFPUnaryOp>; +def fsqrt : SDNode<"ISD::FSQRT" , SDTFPUnaryOp>; +def fsin : SDNode<"ISD::FSIN" , SDTFPUnaryOp>; +def fcos : SDNode<"ISD::FCOS" , SDTFPUnaryOp>; +def fexp2 : SDNode<"ISD::FEXP2" , SDTFPUnaryOp>; +def fpow : SDNode<"ISD::FPOW" , SDTFPBinOp>; +def flog2 : SDNode<"ISD::FLOG2" , SDTFPUnaryOp>; +def frint : SDNode<"ISD::FRINT" , SDTFPUnaryOp>; +def ftrunc : SDNode<"ISD::FTRUNC" , SDTFPUnaryOp>; +def fceil : SDNode<"ISD::FCEIL" , SDTFPUnaryOp>; +def ffloor : SDNode<"ISD::FFLOOR" , SDTFPUnaryOp>; +def fnearbyint : SDNode<"ISD::FNEARBYINT" , SDTFPUnaryOp>; +def fround : SDNode<"ISD::FROUND" , SDTFPUnaryOp>; + +def fpround : SDNode<"ISD::FP_ROUND" , SDTFPRoundOp>; +def fpextend : SDNode<"ISD::FP_EXTEND" , SDTFPExtendOp>; +def fcopysign : SDNode<"ISD::FCOPYSIGN" , SDTFPSignOp>; + +def sint_to_fp : SDNode<"ISD::SINT_TO_FP" , SDTIntToFPOp>; +def uint_to_fp : SDNode<"ISD::UINT_TO_FP" , SDTIntToFPOp>; +def fp_to_sint : SDNode<"ISD::FP_TO_SINT" , SDTFPToIntOp>; +def fp_to_uint : SDNode<"ISD::FP_TO_UINT" , SDTFPToIntOp>; +def f16_to_fp : SDNode<"ISD::FP16_TO_FP" , SDTIntToFPOp>; +def fp_to_f16 : SDNode<"ISD::FP_TO_FP16" , SDTFPToIntOp>; + +def setcc : SDNode<"ISD::SETCC" , SDTSetCC>; +def select : SDNode<"ISD::SELECT" , SDTSelect>; +def vselect : SDNode<"ISD::VSELECT" , SDTVSelect>; +def selectcc : SDNode<"ISD::SELECT_CC" , SDTSelectCC>; + +def brcc : SDNode<"ISD::BR_CC" , SDTBrCC, [SDNPHasChain]>; +def brcond : SDNode<"ISD::BRCOND" , SDTBrcond, [SDNPHasChain]>; +def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>; +def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>; +def catchret : SDNode<"ISD::CATCHRET" , SDTCatchret, + [SDNPHasChain, SDNPSideEffect]>; +def cleanupret : SDNode<"ISD::CLEANUPRET" , SDTNone, [SDNPHasChain]>; +def catchpad : SDNode<"ISD::CATCHPAD" , SDTNone, + [SDNPHasChain, SDNPSideEffect]>; + +def trap : SDNode<"ISD::TRAP" , SDTNone, + [SDNPHasChain, SDNPSideEffect]>; +def debugtrap : SDNode<"ISD::DEBUGTRAP" , SDTNone, + [SDNPHasChain, SDNPSideEffect]>; + +def prefetch : SDNode<"ISD::PREFETCH" , SDTPrefetch, + [SDNPHasChain, SDNPMayLoad, SDNPMayStore, + SDNPMemOperand]>; + +def readcyclecounter : SDNode<"ISD::READCYCLECOUNTER", SDTIntLeaf, + [SDNPHasChain, SDNPSideEffect]>; + +def atomic_fence : SDNode<"ISD::ATOMIC_FENCE" , SDTAtomicFence, + [SDNPHasChain, SDNPSideEffect]>; + +def atomic_cmp_swap : SDNode<"ISD::ATOMIC_CMP_SWAP" , SDTAtomic3, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_add : SDNode<"ISD::ATOMIC_LOAD_ADD" , SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_swap : SDNode<"ISD::ATOMIC_SWAP", SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_sub : SDNode<"ISD::ATOMIC_LOAD_SUB" , SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_and : SDNode<"ISD::ATOMIC_LOAD_AND" , SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_clr : SDNode<"ISD::ATOMIC_LOAD_CLR" , SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_or : SDNode<"ISD::ATOMIC_LOAD_OR" , SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_xor : SDNode<"ISD::ATOMIC_LOAD_XOR" , SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_nand: SDNode<"ISD::ATOMIC_LOAD_NAND", SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_min : SDNode<"ISD::ATOMIC_LOAD_MIN", SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_max : SDNode<"ISD::ATOMIC_LOAD_MAX", SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_umin : SDNode<"ISD::ATOMIC_LOAD_UMIN", SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_umax : SDNode<"ISD::ATOMIC_LOAD_UMAX", SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load : SDNode<"ISD::ATOMIC_LOAD", SDTAtomicLoad, + [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; +def atomic_store : SDNode<"ISD::ATOMIC_STORE", SDTAtomicStore, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; + +def masked_store : SDNode<"ISD::MSTORE", SDTMaskedStore, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; +def masked_load : SDNode<"ISD::MLOAD", SDTMaskedLoad, + [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; +def masked_scatter : SDNode<"ISD::MSCATTER", SDTMaskedScatter, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; +def masked_gather : SDNode<"ISD::MGATHER", SDTMaskedGather, + [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; + +// Do not use ld, st directly. Use load, extload, sextload, zextload, store, +// and truncst (see below). +def ld : SDNode<"ISD::LOAD" , SDTLoad, + [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; +def st : SDNode<"ISD::STORE" , SDTStore, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; +def ist : SDNode<"ISD::STORE" , SDTIStore, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; + +def vector_shuffle : SDNode<"ISD::VECTOR_SHUFFLE", SDTVecShuffle, []>; +def build_vector : SDNode<"ISD::BUILD_VECTOR", SDTypeProfile<1, -1, []>, []>; +def scalar_to_vector : SDNode<"ISD::SCALAR_TO_VECTOR", SDTypeProfile<1, 1, []>, + []>; + +// vector_extract/vector_insert are deprecated. extractelt/insertelt +// are preferred. +def vector_extract : SDNode<"ISD::EXTRACT_VECTOR_ELT", + SDTypeProfile<1, 2, [SDTCisPtrTy<2>]>, []>; +def vector_insert : SDNode<"ISD::INSERT_VECTOR_ELT", + SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisPtrTy<3>]>, []>; +def concat_vectors : SDNode<"ISD::CONCAT_VECTORS", + SDTypeProfile<1, 2, [SDTCisSubVecOfVec<1, 0>, SDTCisSameAs<1, 2>]>,[]>; + +// This operator does not do subvector type checking. The ARM +// backend, at least, needs it. +def vector_extract_subvec : SDNode<"ISD::EXTRACT_SUBVECTOR", + SDTypeProfile<1, 2, [SDTCisInt<2>, SDTCisVec<1>, SDTCisVec<0>]>, + []>; + +// This operator does subvector type checking. +def extract_subvector : SDNode<"ISD::EXTRACT_SUBVECTOR", SDTSubVecExtract, []>; +def insert_subvector : SDNode<"ISD::INSERT_SUBVECTOR", SDTSubVecInsert, []>; + +// Nodes for intrinsics, you should use the intrinsic itself and let tblgen use +// these internally. Don't reference these directly. +def intrinsic_void : SDNode<"ISD::INTRINSIC_VOID", + SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>, + [SDNPHasChain]>; +def intrinsic_w_chain : SDNode<"ISD::INTRINSIC_W_CHAIN", + SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>, + [SDNPHasChain]>; +def intrinsic_wo_chain : SDNode<"ISD::INTRINSIC_WO_CHAIN", + SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>, []>; + +def SDT_assertext : SDTypeProfile<1, 1, + [SDTCisInt<0>, SDTCisInt<1>, SDTCisSameAs<1, 0>]>; +def assertsext : SDNode<"ISD::AssertSext", SDT_assertext>; +def assertzext : SDNode<"ISD::AssertZext", SDT_assertext>; + + +//===----------------------------------------------------------------------===// +// Selection DAG Condition Codes + +class CondCode; // ISD::CondCode enums +def SETOEQ : CondCode; def SETOGT : CondCode; +def SETOGE : CondCode; def SETOLT : CondCode; def SETOLE : CondCode; +def SETONE : CondCode; def SETO : CondCode; def SETUO : CondCode; +def SETUEQ : CondCode; def SETUGT : CondCode; def SETUGE : CondCode; +def SETULT : CondCode; def SETULE : CondCode; def SETUNE : CondCode; + +def SETEQ : CondCode; def SETGT : CondCode; def SETGE : CondCode; +def SETLT : CondCode; def SETLE : CondCode; def SETNE : CondCode; + + +//===----------------------------------------------------------------------===// +// Selection DAG Node Transformation Functions. +// +// This mechanism allows targets to manipulate nodes in the output DAG once a +// match has been formed. This is typically used to manipulate immediate +// values. +// +class SDNodeXForm<SDNode opc, code xformFunction> { + SDNode Opcode = opc; + code XFormFunction = xformFunction; +} + +def NOOP_SDNodeXForm : SDNodeXForm<imm, [{}]>; + +//===----------------------------------------------------------------------===// +// PatPred Subclasses. +// +// These allow specifying different sorts of predicates that control whether a +// node is matched. +// +class PatPred; + +class CodePatPred<code predicate> : PatPred { + code PredicateCode = predicate; +} + + +//===----------------------------------------------------------------------===// +// Selection DAG Pattern Fragments. +// +// Pattern fragments are reusable chunks of dags that match specific things. +// They can take arguments and have C++ predicates that control whether they +// match. They are intended to make the patterns for common instructions more +// compact and readable. +// + +/// PatFrags - Represents a set of pattern fragments. Each single fragment +/// can match something on the DAG, from a single node to multiple nested other +/// fragments. The whole set of fragments matches if any of the single +/// fragemnts match. This allows e.g. matching and "add with overflow" and +/// a regular "add" with the same fragment set. +/// +class PatFrags<dag ops, list<dag> frags, code pred = [{}], + SDNodeXForm xform = NOOP_SDNodeXForm> : SDPatternOperator { + dag Operands = ops; + list<dag> Fragments = frags; + code PredicateCode = pred; + code GISelPredicateCode = [{}]; + code ImmediateCode = [{}]; + SDNodeXForm OperandTransform = xform; + + // Define a few pre-packaged predicates. This helps GlobalISel import + // existing rules from SelectionDAG for many common cases. + // They will be tested prior to the code in pred and must not be used in + // ImmLeaf and its subclasses. + + // Is the desired pre-packaged predicate for a load? + bit IsLoad = ?; + // Is the desired pre-packaged predicate for a store? + bit IsStore = ?; + // Is the desired pre-packaged predicate for an atomic? + bit IsAtomic = ?; + + // cast<LoadSDNode>(N)->getAddressingMode() == ISD::UNINDEXED; + // cast<StoreSDNode>(N)->getAddressingMode() == ISD::UNINDEXED; + bit IsUnindexed = ?; + + // cast<LoadSDNode>(N)->getExtensionType() != ISD::NON_EXTLOAD + bit IsNonExtLoad = ?; + // cast<LoadSDNode>(N)->getExtensionType() == ISD::EXTLOAD; + bit IsAnyExtLoad = ?; + // cast<LoadSDNode>(N)->getExtensionType() == ISD::SEXTLOAD; + bit IsSignExtLoad = ?; + // cast<LoadSDNode>(N)->getExtensionType() == ISD::ZEXTLOAD; + bit IsZeroExtLoad = ?; + // !cast<StoreSDNode>(N)->isTruncatingStore(); + // cast<StoreSDNode>(N)->isTruncatingStore(); + bit IsTruncStore = ?; + + // cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::Monotonic + bit IsAtomicOrderingMonotonic = ?; + // cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::Acquire + bit IsAtomicOrderingAcquire = ?; + // cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::Release + bit IsAtomicOrderingRelease = ?; + // cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::AcquireRelease + bit IsAtomicOrderingAcquireRelease = ?; + // cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::SequentiallyConsistent + bit IsAtomicOrderingSequentiallyConsistent = ?; + + // isAcquireOrStronger(cast<AtomicSDNode>(N)->getOrdering()) + // !isAcquireOrStronger(cast<AtomicSDNode>(N)->getOrdering()) + bit IsAtomicOrderingAcquireOrStronger = ?; + + // isReleaseOrStronger(cast<AtomicSDNode>(N)->getOrdering()) + // !isReleaseOrStronger(cast<AtomicSDNode>(N)->getOrdering()) + bit IsAtomicOrderingReleaseOrStronger = ?; + + // cast<LoadSDNode>(N)->getMemoryVT() == MVT::<VT>; + // cast<StoreSDNode>(N)->getMemoryVT() == MVT::<VT>; + ValueType MemoryVT = ?; + // cast<LoadSDNode>(N)->getMemoryVT().getScalarType() == MVT::<VT>; + // cast<StoreSDNode>(N)->getMemoryVT().getScalarType() == MVT::<VT>; + ValueType ScalarMemoryVT = ?; +} + +// PatFrag - A version of PatFrags matching only a single fragment. +class PatFrag<dag ops, dag frag, code pred = [{}], + SDNodeXForm xform = NOOP_SDNodeXForm> + : PatFrags<ops, [frag], pred, xform>; + +// OutPatFrag is a pattern fragment that is used as part of an output pattern +// (not an input pattern). These do not have predicates or transforms, but are +// used to avoid repeated subexpressions in output patterns. +class OutPatFrag<dag ops, dag frag> + : PatFrag<ops, frag, [{}], NOOP_SDNodeXForm>; + +// PatLeaf's are pattern fragments that have no operands. This is just a helper +// to define immediates and other common things concisely. +class PatLeaf<dag frag, code pred = [{}], SDNodeXForm xform = NOOP_SDNodeXForm> + : PatFrag<(ops), frag, pred, xform>; + + +// ImmLeaf is a pattern fragment with a constraint on the immediate. The +// constraint is a function that is run on the immediate (always with the value +// sign extended out to an int64_t) as Imm. For example: +// +// def immSExt8 : ImmLeaf<i16, [{ return (char)Imm == Imm; }]>; +// +// this is a more convenient form to match 'imm' nodes in than PatLeaf and also +// is preferred over using PatLeaf because it allows the code generator to +// reason more about the constraint. +// +// If FastIsel should ignore all instructions that have an operand of this type, +// the FastIselShouldIgnore flag can be set. This is an optimization to reduce +// the code size of the generated fast instruction selector. +class ImmLeaf<ValueType vt, code pred, SDNodeXForm xform = NOOP_SDNodeXForm, + SDNode ImmNode = imm> + : PatFrag<(ops), (vt ImmNode), [{}], xform> { + let ImmediateCode = pred; + bit FastIselShouldIgnore = 0; + + // Is the data type of the immediate an APInt? + bit IsAPInt = 0; + + // Is the data type of the immediate an APFloat? + bit IsAPFloat = 0; +} + +// An ImmLeaf except that Imm is an APInt. This is useful when you need to +// zero-extend the immediate instead of sign-extend it. +// +// Note that FastISel does not currently understand IntImmLeaf and will not +// generate code for rules that make use of it. As such, it does not make sense +// to replace ImmLeaf with IntImmLeaf. However, replacing PatLeaf with an +// IntImmLeaf will allow GlobalISel to import the rule. +class IntImmLeaf<ValueType vt, code pred, SDNodeXForm xform = NOOP_SDNodeXForm> + : ImmLeaf<vt, pred, xform> { + let IsAPInt = 1; + let FastIselShouldIgnore = 1; +} + +// An ImmLeaf except that Imm is an APFloat. +// +// Note that FastISel does not currently understand FPImmLeaf and will not +// generate code for rules that make use of it. +class FPImmLeaf<ValueType vt, code pred, SDNodeXForm xform = NOOP_SDNodeXForm> + : ImmLeaf<vt, pred, xform, fpimm> { + let IsAPFloat = 1; + let FastIselShouldIgnore = 1; +} + +// Leaf fragments. + +def vtInt : PatLeaf<(vt), [{ return N->getVT().isInteger(); }]>; +def vtFP : PatLeaf<(vt), [{ return N->getVT().isFloatingPoint(); }]>; + +def immAllOnesV: PatLeaf<(build_vector), [{ + return ISD::isBuildVectorAllOnes(N); +}]>; +def immAllZerosV: PatLeaf<(build_vector), [{ + return ISD::isBuildVectorAllZeros(N); +}]>; + + + +// Other helper fragments. +def not : PatFrag<(ops node:$in), (xor node:$in, -1)>; +def vnot : PatFrag<(ops node:$in), (xor node:$in, immAllOnesV)>; +def ineg : PatFrag<(ops node:$in), (sub 0, node:$in)>; + +// null_frag - The null pattern operator is used in multiclass instantiations +// which accept an SDPatternOperator for use in matching patterns for internal +// definitions. When expanding a pattern, if the null fragment is referenced +// in the expansion, the pattern is discarded and it is as-if '[]' had been +// specified. This allows multiclasses to have the isel patterns be optional. +def null_frag : SDPatternOperator; + +// load fragments. +def unindexedload : PatFrag<(ops node:$ptr), (ld node:$ptr)> { + let IsLoad = 1; + let IsUnindexed = 1; +} +def load : PatFrag<(ops node:$ptr), (unindexedload node:$ptr)> { + let IsLoad = 1; + let IsNonExtLoad = 1; +} + +// extending load fragments. +def extload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr)> { + let IsLoad = 1; + let IsAnyExtLoad = 1; +} +def sextload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr)> { + let IsLoad = 1; + let IsSignExtLoad = 1; +} +def zextload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr)> { + let IsLoad = 1; + let IsZeroExtLoad = 1; +} + +def extloadi1 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i1; +} +def extloadi8 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i8; +} +def extloadi16 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i16; +} +def extloadi32 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i32; +} +def extloadf32 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = f32; +} +def extloadf64 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = f64; +} + +def sextloadi1 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i1; +} +def sextloadi8 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i8; +} +def sextloadi16 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i16; +} +def sextloadi32 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i32; +} + +def zextloadi1 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i1; +} +def zextloadi8 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i8; +} +def zextloadi16 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i16; +} +def zextloadi32 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { + let IsLoad = 1; + let MemoryVT = i32; +} + +def extloadvi1 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i1; +} +def extloadvi8 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i8; +} +def extloadvi16 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i16; +} +def extloadvi32 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i32; +} +def extloadvf32 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = f32; +} +def extloadvf64 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = f64; +} + +def sextloadvi1 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i1; +} +def sextloadvi8 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i8; +} +def sextloadvi16 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i16; +} +def sextloadvi32 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i32; +} + +def zextloadvi1 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i1; +} +def zextloadvi8 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i8; +} +def zextloadvi16 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i16; +} +def zextloadvi32 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { + let IsLoad = 1; + let ScalarMemoryVT = i32; +} + +// store fragments. +def unindexedstore : PatFrag<(ops node:$val, node:$ptr), + (st node:$val, node:$ptr)> { + let IsStore = 1; + let IsUnindexed = 1; +} +def store : PatFrag<(ops node:$val, node:$ptr), + (unindexedstore node:$val, node:$ptr)> { + let IsStore = 1; + let IsTruncStore = 0; +} + +// truncstore fragments. +def truncstore : PatFrag<(ops node:$val, node:$ptr), + (unindexedstore node:$val, node:$ptr)> { + let IsStore = 1; + let IsTruncStore = 1; +} +def truncstorei8 : PatFrag<(ops node:$val, node:$ptr), + (truncstore node:$val, node:$ptr)> { + let IsStore = 1; + let MemoryVT = i8; +} +def truncstorei16 : PatFrag<(ops node:$val, node:$ptr), + (truncstore node:$val, node:$ptr)> { + let IsStore = 1; + let MemoryVT = i16; +} +def truncstorei32 : PatFrag<(ops node:$val, node:$ptr), + (truncstore node:$val, node:$ptr)> { + let IsStore = 1; + let MemoryVT = i32; +} +def truncstoref32 : PatFrag<(ops node:$val, node:$ptr), + (truncstore node:$val, node:$ptr)> { + let IsStore = 1; + let MemoryVT = f32; +} +def truncstoref64 : PatFrag<(ops node:$val, node:$ptr), + (truncstore node:$val, node:$ptr)> { + let IsStore = 1; + let MemoryVT = f64; +} + +def truncstorevi8 : PatFrag<(ops node:$val, node:$ptr), + (truncstore node:$val, node:$ptr)> { + let IsStore = 1; + let ScalarMemoryVT = i8; +} + +def truncstorevi16 : PatFrag<(ops node:$val, node:$ptr), + (truncstore node:$val, node:$ptr)> { + let IsStore = 1; + let ScalarMemoryVT = i16; +} + +def truncstorevi32 : PatFrag<(ops node:$val, node:$ptr), + (truncstore node:$val, node:$ptr)> { + let IsStore = 1; + let ScalarMemoryVT = i32; +} + +// indexed store fragments. +def istore : PatFrag<(ops node:$val, node:$base, node:$offset), + (ist node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let IsTruncStore = 0; +} + +def pre_store : PatFrag<(ops node:$val, node:$base, node:$offset), + (istore node:$val, node:$base, node:$offset), [{ + ISD::MemIndexedMode AM = cast<StoreSDNode>(N)->getAddressingMode(); + return AM == ISD::PRE_INC || AM == ISD::PRE_DEC; +}]>; + +def itruncstore : PatFrag<(ops node:$val, node:$base, node:$offset), + (ist node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let IsTruncStore = 1; +} +def pre_truncst : PatFrag<(ops node:$val, node:$base, node:$offset), + (itruncstore node:$val, node:$base, node:$offset), [{ + ISD::MemIndexedMode AM = cast<StoreSDNode>(N)->getAddressingMode(); + return AM == ISD::PRE_INC || AM == ISD::PRE_DEC; +}]>; +def pre_truncsti1 : PatFrag<(ops node:$val, node:$base, node:$offset), + (pre_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = i1; +} +def pre_truncsti8 : PatFrag<(ops node:$val, node:$base, node:$offset), + (pre_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = i8; +} +def pre_truncsti16 : PatFrag<(ops node:$val, node:$base, node:$offset), + (pre_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = i16; +} +def pre_truncsti32 : PatFrag<(ops node:$val, node:$base, node:$offset), + (pre_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = i32; +} +def pre_truncstf32 : PatFrag<(ops node:$val, node:$base, node:$offset), + (pre_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = f32; +} + +def post_store : PatFrag<(ops node:$val, node:$ptr, node:$offset), + (istore node:$val, node:$ptr, node:$offset), [{ + ISD::MemIndexedMode AM = cast<StoreSDNode>(N)->getAddressingMode(); + return AM == ISD::POST_INC || AM == ISD::POST_DEC; +}]>; + +def post_truncst : PatFrag<(ops node:$val, node:$base, node:$offset), + (itruncstore node:$val, node:$base, node:$offset), [{ + ISD::MemIndexedMode AM = cast<StoreSDNode>(N)->getAddressingMode(); + return AM == ISD::POST_INC || AM == ISD::POST_DEC; +}]>; +def post_truncsti1 : PatFrag<(ops node:$val, node:$base, node:$offset), + (post_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = i1; +} +def post_truncsti8 : PatFrag<(ops node:$val, node:$base, node:$offset), + (post_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = i8; +} +def post_truncsti16 : PatFrag<(ops node:$val, node:$base, node:$offset), + (post_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = i16; +} +def post_truncsti32 : PatFrag<(ops node:$val, node:$base, node:$offset), + (post_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = i32; +} +def post_truncstf32 : PatFrag<(ops node:$val, node:$base, node:$offset), + (post_truncst node:$val, node:$base, node:$offset)> { + let IsStore = 1; + let MemoryVT = f32; +} + +// nontemporal store fragments. +def nontemporalstore : PatFrag<(ops node:$val, node:$ptr), + (store node:$val, node:$ptr), [{ + return cast<StoreSDNode>(N)->isNonTemporal(); +}]>; + +def alignednontemporalstore : PatFrag<(ops node:$val, node:$ptr), + (nontemporalstore node:$val, node:$ptr), [{ + StoreSDNode *St = cast<StoreSDNode>(N); + return St->getAlignment() >= St->getMemoryVT().getStoreSize(); +}]>; + +def unalignednontemporalstore : PatFrag<(ops node:$val, node:$ptr), + (nontemporalstore node:$val, node:$ptr), [{ + StoreSDNode *St = cast<StoreSDNode>(N); + return St->getAlignment() < St->getMemoryVT().getStoreSize(); +}]>; + +// nontemporal load fragments. +def nontemporalload : PatFrag<(ops node:$ptr), + (load node:$ptr), [{ + return cast<LoadSDNode>(N)->isNonTemporal(); +}]>; + +def alignednontemporalload : PatFrag<(ops node:$ptr), + (nontemporalload node:$ptr), [{ + LoadSDNode *Ld = cast<LoadSDNode>(N); + return Ld->getAlignment() >= Ld->getMemoryVT().getStoreSize(); +}]>; + +// setcc convenience fragments. +def setoeq : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETOEQ)>; +def setogt : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETOGT)>; +def setoge : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETOGE)>; +def setolt : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETOLT)>; +def setole : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETOLE)>; +def setone : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETONE)>; +def seto : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETO)>; +def setuo : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETUO)>; +def setueq : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETUEQ)>; +def setugt : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETUGT)>; +def setuge : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETUGE)>; +def setult : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETULT)>; +def setule : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETULE)>; +def setune : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETUNE)>; +def seteq : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETEQ)>; +def setgt : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETGT)>; +def setge : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETGE)>; +def setlt : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETLT)>; +def setle : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETLE)>; +def setne : PatFrag<(ops node:$lhs, node:$rhs), + (setcc node:$lhs, node:$rhs, SETNE)>; + +multiclass binary_atomic_op_ord<SDNode atomic_op> { + def #NAME#_monotonic : PatFrag<(ops node:$ptr, node:$val), + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingMonotonic = 1; + } + def #NAME#_acquire : PatFrag<(ops node:$ptr, node:$val), + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingAcquire = 1; + } + def #NAME#_release : PatFrag<(ops node:$ptr, node:$val), + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingRelease = 1; + } + def #NAME#_acq_rel : PatFrag<(ops node:$ptr, node:$val), + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingAcquireRelease = 1; + } + def #NAME#_seq_cst : PatFrag<(ops node:$ptr, node:$val), + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingSequentiallyConsistent = 1; + } +} + +multiclass ternary_atomic_op_ord<SDNode atomic_op> { + def #NAME#_monotonic : PatFrag<(ops node:$ptr, node:$cmp, node:$val), + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingMonotonic = 1; + } + def #NAME#_acquire : PatFrag<(ops node:$ptr, node:$cmp, node:$val), + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingAcquire = 1; + } + def #NAME#_release : PatFrag<(ops node:$ptr, node:$cmp, node:$val), + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingRelease = 1; + } + def #NAME#_acq_rel : PatFrag<(ops node:$ptr, node:$cmp, node:$val), + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingAcquireRelease = 1; + } + def #NAME#_seq_cst : PatFrag<(ops node:$ptr, node:$cmp, node:$val), + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> { + let IsAtomic = 1; + let IsAtomicOrderingSequentiallyConsistent = 1; + } +} + +multiclass binary_atomic_op<SDNode atomic_op> { + def _8 : PatFrag<(ops node:$ptr, node:$val), + (atomic_op node:$ptr, node:$val)> { + let IsAtomic = 1; + let MemoryVT = i8; + } + def _16 : PatFrag<(ops node:$ptr, node:$val), + (atomic_op node:$ptr, node:$val)> { + let IsAtomic = 1; + let MemoryVT = i16; + } + def _32 : PatFrag<(ops node:$ptr, node:$val), + (atomic_op node:$ptr, node:$val)> { + let IsAtomic = 1; + let MemoryVT = i32; + } + def _64 : PatFrag<(ops node:$ptr, node:$val), + (atomic_op node:$ptr, node:$val)> { + let IsAtomic = 1; + let MemoryVT = i64; + } + + defm NAME#_8 : binary_atomic_op_ord<atomic_op>; + defm NAME#_16 : binary_atomic_op_ord<atomic_op>; + defm NAME#_32 : binary_atomic_op_ord<atomic_op>; + defm NAME#_64 : binary_atomic_op_ord<atomic_op>; +} + +multiclass ternary_atomic_op<SDNode atomic_op> { + def _8 : PatFrag<(ops node:$ptr, node:$cmp, node:$val), + (atomic_op node:$ptr, node:$cmp, node:$val)> { + let IsAtomic = 1; + let MemoryVT = i8; + } + def _16 : PatFrag<(ops node:$ptr, node:$cmp, node:$val), + (atomic_op node:$ptr, node:$cmp, node:$val)> { + let IsAtomic = 1; + let MemoryVT = i16; + } + def _32 : PatFrag<(ops node:$ptr, node:$cmp, node:$val), + (atomic_op node:$ptr, node:$cmp, node:$val)> { + let IsAtomic = 1; + let MemoryVT = i32; + } + def _64 : PatFrag<(ops node:$ptr, node:$cmp, node:$val), + (atomic_op node:$ptr, node:$cmp, node:$val)> { + let IsAtomic = 1; + let MemoryVT = i64; + } + + defm NAME#_8 : ternary_atomic_op_ord<atomic_op>; + defm NAME#_16 : ternary_atomic_op_ord<atomic_op>; + defm NAME#_32 : ternary_atomic_op_ord<atomic_op>; + defm NAME#_64 : ternary_atomic_op_ord<atomic_op>; +} + +defm atomic_load_add : binary_atomic_op<atomic_load_add>; +defm atomic_swap : binary_atomic_op<atomic_swap>; +defm atomic_load_sub : binary_atomic_op<atomic_load_sub>; +defm atomic_load_and : binary_atomic_op<atomic_load_and>; +defm atomic_load_clr : binary_atomic_op<atomic_load_clr>; +defm atomic_load_or : binary_atomic_op<atomic_load_or>; +defm atomic_load_xor : binary_atomic_op<atomic_load_xor>; +defm atomic_load_nand : binary_atomic_op<atomic_load_nand>; +defm atomic_load_min : binary_atomic_op<atomic_load_min>; +defm atomic_load_max : binary_atomic_op<atomic_load_max>; +defm atomic_load_umin : binary_atomic_op<atomic_load_umin>; +defm atomic_load_umax : binary_atomic_op<atomic_load_umax>; +defm atomic_store : binary_atomic_op<atomic_store>; +defm atomic_cmp_swap : ternary_atomic_op<atomic_cmp_swap>; + +def atomic_load_8 : + PatFrag<(ops node:$ptr), + (atomic_load node:$ptr)> { + let IsAtomic = 1; + let MemoryVT = i8; +} +def atomic_load_16 : + PatFrag<(ops node:$ptr), + (atomic_load node:$ptr)> { + let IsAtomic = 1; + let MemoryVT = i16; +} +def atomic_load_32 : + PatFrag<(ops node:$ptr), + (atomic_load node:$ptr)> { + let IsAtomic = 1; + let MemoryVT = i32; +} +def atomic_load_64 : + PatFrag<(ops node:$ptr), + (atomic_load node:$ptr)> { + let IsAtomic = 1; + let MemoryVT = i64; +} + +//===----------------------------------------------------------------------===// +// Selection DAG Pattern Support. +// +// Patterns are what are actually matched against by the target-flavored +// instruction selection DAG. Instructions defined by the target implicitly +// define patterns in most cases, but patterns can also be explicitly added when +// an operation is defined by a sequence of instructions (e.g. loading a large +// immediate value on RISC targets that do not support immediates as large as +// their GPRs). +// + +class Pattern<dag patternToMatch, list<dag> resultInstrs> { + dag PatternToMatch = patternToMatch; + list<dag> ResultInstrs = resultInstrs; + list<Predicate> Predicates = []; // See class Instruction in Target.td. + int AddedComplexity = 0; // See class Instruction in Target.td. +} + +// Pat - A simple (but common) form of a pattern, which produces a simple result +// not needing a full list. +class Pat<dag pattern, dag result> : Pattern<pattern, [result]>; + +//===----------------------------------------------------------------------===// +// Complex pattern definitions. +// + +// Complex patterns, e.g. X86 addressing mode, requires pattern matching code +// in C++. NumOperands is the number of operands returned by the select function; +// SelectFunc is the name of the function used to pattern match the max. pattern; +// RootNodes are the list of possible root nodes of the sub-dags to match. +// e.g. X86 addressing mode - def addr : ComplexPattern<4, "SelectAddr", [add]>; +// +class ComplexPattern<ValueType ty, int numops, string fn, + list<SDNode> roots = [], list<SDNodeProperty> props = [], + int complexity = -1> { + ValueType Ty = ty; + int NumOperands = numops; + string SelectFunc = fn; + list<SDNode> RootNodes = roots; + list<SDNodeProperty> Properties = props; + int Complexity = complexity; +} |