SDTCisInt<0>, SDTCisVT<1, OtherVT>
]>;
+def SDTBrind : SDTypeProfile<0, 1, [ // brind
+ SDTCisPtrTy<0>
+]>;
+
def SDTRet : SDTypeProfile<0, 0, []>; // ret
def SDTLoad : SDTypeProfile<1, 1, [ // load
SDTCisPtrTy<1>
]>;
-def SDTExtLoad : SDTypeProfile<1, 3, [ // extload
- SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>, SDTCisVT<3, OtherVT>
-]>;
-def SDTIntExtLoad : SDTypeProfile<1, 3, [ // sextload, zextload
- SDTCisInt<0>, SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>, SDTCisVT<3, OtherVT>
-]>;
-def SDTTruncStore : SDTypeProfile<0, 4, [ // truncstore
- SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>, SDTCisVT<3, OtherVT>
+def SDTIStore : SDTypeProfile<1, 3, [ // indexed store
+ SDTCisSameAs<0, 2>, SDTCisPtrTy<0>, SDTCisPtrTy<3>
]>;
def SDTVecShuffle : SDTypeProfile<1, 3, [
"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, [],
def selectcc : SDNode<"ISD::SELECT_CC" , SDTSelectCC>;
def brcond : SDNode<"ISD::BRCOND" , SDTBrcond, [SDNPHasChain]>;
+def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>;
def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>;
def ret : SDNode<"ISD::RET" , SDTRet, [SDNPHasChain]>;
-def load : SDNode<"ISD::LOAD" , SDTLoad, [SDNPHasChain]>;
-def store : SDNode<"ISD::STORE" , SDTStore, [SDNPHasChain]>;
-
-// Do not use sextld and zextld directly. Use sextload and zextload (see
-// below) which pass in a dummy srcvalue node which tblgen will skip over.
-def sextld : SDNode<"ISD::SEXTLOAD" , SDTIntExtLoad, [SDNPHasChain]>;
-def zextld : SDNode<"ISD::ZEXTLOAD" , SDTIntExtLoad, [SDNPHasChain]>;
-def extld : SDNode<"ISD::EXTLOAD" , SDTExtLoad, [SDNPHasChain]>;
-def truncst : SDNode<"ISD::TRUNCSTORE" , SDTTruncStore, [SDNPHasChain]>;
+// Do not use ld, st directly. Use load, extload, sextload, zextload, store,
+// and truncst (see below).
+def ld : SDNode<"ISD::LOAD" , SDTLoad, [SDNPHasChain]>;
+def st : SDNode<"ISD::STORE" , SDTStore, [SDNPHasChain]>;
+def ist : SDNode<"ISD::STORE" , SDTIStore, [SDNPHasChain]>;
def vector_shuffle : SDNode<"ISD::VECTOR_SHUFFLE", SDTVecShuffle, []>;
def build_vector : SDNode<"ISD::BUILD_VECTOR", SDTypeProfile<1, 0, []>, []>;
def scalar_to_vector : SDNode<"ISD::SCALAR_TO_VECTOR", SDTypeProfile<1, 1, []>,
[]>;
+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>]>, []>;
// 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",
+def intrinsic_void : SDNode<"ISD::INTRINSIC_VOID",
SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>,
[SDNPHasChain]>;
-def intrinsic_w_chain : SDNode<"ISD::INTRINSIC",
+def intrinsic_w_chain : SDNode<"ISD::INTRINSIC_W_CHAIN",
SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>,
[SDNPHasChain]>;
-def intrinsic_wo_chain : SDNode<"ISD::INTRINSIC",
+def intrinsic_wo_chain : SDNode<"ISD::INTRINSIC_WO_CHAIN",
SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>, []>;
// Leaf fragments.
-def immAllOnes : PatLeaf<(imm), [{ return N->isAllOnesValue(); }]>;
def vtInt : PatLeaf<(vt), [{ return MVT::isInteger(N->getVT()); }]>;
def vtFP : PatLeaf<(vt), [{ return MVT::isFloatingPoint(N->getVT()); }]>;
-// Other helper fragments.
+def immAllOnes : PatLeaf<(imm), [{ return N->isAllOnesValue(); }]>;
+def immAllOnesV: PatLeaf<(build_vector), [{
+ return ISD::isBuildVectorAllOnes(N);
+}]>;
+def immAllZerosV: PatLeaf<(build_vector), [{
+ return ISD::isBuildVectorAllZeros(N);
+}]>;
+
+def immAllOnesV_bc: PatLeaf<(bitconvert), [{
+ return ISD::isBuildVectorAllOnes(N);
+}]>;
+
+// Other helper fragments.
def not : PatFrag<(ops node:$in), (xor node:$in, immAllOnes)>;
+def vnot : PatFrag<(ops node:$in), (xor node:$in, immAllOnesV)>;
+def vnot_conv : PatFrag<(ops node:$in), (xor node:$in, immAllOnesV_bc)>;
def ineg : PatFrag<(ops node:$in), (sub 0, node:$in)>;
-// extending load & truncstore fragments.
-def sextload : PatFrag<(ops node:$ptr, node:$vt),
- (sextld node:$ptr, srcvalue:$dummy, node:$vt)>;
-def zextload : PatFrag<(ops node:$ptr, node:$vt),
- (zextld node:$ptr, srcvalue:$dummy, node:$vt)>;
-def extload : PatFrag<(ops node:$ptr, node:$vt),
- (extld node:$ptr, srcvalue:$dummy, node:$vt)>;
-def truncstore : PatFrag<(ops node:$val, node:$ptr, node:$vt),
- (truncst node:$val, node:$ptr, srcvalue:$dummy,
- node:$vt)>;
+// load fragments.
+def load : PatFrag<(ops node:$ptr), (ld node:$ptr), [{
+ if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N))
+ return LD->getExtensionType() == ISD::NON_EXTLOAD &&
+ LD->getAddressingMode() == ISD::UNINDEXED;
+ return false;
+}]>;
+
+// extending load fragments.
+def extloadi1 : PatFrag<(ops node:$ptr), (ld node:$ptr), [{
+ if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N))
+ return LD->getExtensionType() == ISD::EXTLOAD &&
+ LD->getAddressingMode() == ISD::UNINDEXED &&
+ LD->getLoadedVT() == MVT::i1;
+ return false;
+}]>;
+def extloadi8 : PatFrag<(ops node:$ptr), (ld node:$ptr), [{
+ if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N))
+ return LD->getExtensionType() == ISD::EXTLOAD &&
+ LD->getAddressingMode() == ISD::UNINDEXED &&
+ LD->getLoadedVT() == MVT::i8;
+ return false;
+}]>;
+def extloadi16 : PatFrag<(ops node:$ptr), (ld node:$ptr), [{
+ if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N))
+ return LD->getExtensionType() == ISD::EXTLOAD &&
+ LD->getAddressingMode() == ISD::UNINDEXED &&
+ LD->getLoadedVT() == MVT::i16;
+ return false;
+}]>;
+def extloadi32 : PatFrag<(ops node:$ptr), (ld node:$ptr), [{
+ if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N))
+ return LD->getExtensionType() == ISD::EXTLOAD &&
+ LD->getAddressingMode() == ISD::UNINDEXED &&
+ LD->getLoadedVT() == MVT::i32;
+ return false;
+}]>;
+def extloadf32 : PatFrag<(ops node:$ptr), (ld node:$ptr), [{
+ if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N))
+ return LD->getExtensionType() == ISD::EXTLOAD &&
+ LD->getAddressingMode() == ISD::UNINDEXED &&
+ LD->getLoadedVT() == MVT::f32;
+ return false;
+}]>;
+
+def sextloadi1 : PatFrag<(ops node:$ptr), (ld node:$ptr), [{
+ if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N))
+ return LD->getExtensionType() == ISD::SEXTLOAD &&
+ LD->getAddressingMode() == ISD::UNINDEXED &&
+ LD->getLoadedVT() == MVT::i1;
+ return false;
+}]>;
+def sextloadi8 : PatFrag<(ops node:$ptr), (ld node:$ptr), [{
+ if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N))
+ return LD->getExtensionType() == ISD::SEXTLOAD &&
+ LD->getAddressingMode() == ISD::UNINDEXED &&
+ LD->getLoadedVT() == MVT::i8;
+ return false;
+}]>;
+def sextloadi16 : PatFrag<(ops node:$ptr), (ld node:$ptr), [{
+ if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N))
+ return LD->getExtensionType() == ISD::SEXTLOAD &&
+ LD->getAddressingMode() == ISD::UNINDEXED &&
+ LD->getLoadedVT() == MVT::i16;
+ return false;
+}]>;
+def sextloadi32 : PatFrag<(ops node:$ptr), (ld node:$ptr), [{
+ if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N))
+ return LD->getExtensionType() == ISD::SEXTLOAD &&
+ LD->getAddressingMode() == ISD::UNINDEXED &&
+ LD->getLoadedVT() == MVT::i32;
+ return false;
+}]>;
+
+def zextloadi1 : PatFrag<(ops node:$ptr), (ld node:$ptr), [{
+ if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N))
+ return LD->getExtensionType() == ISD::ZEXTLOAD &&
+ LD->getAddressingMode() == ISD::UNINDEXED &&
+ LD->getLoadedVT() == MVT::i1;
+ return false;
+}]>;
+def zextloadi8 : PatFrag<(ops node:$ptr), (ld node:$ptr), [{
+ if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N))
+ return LD->getExtensionType() == ISD::ZEXTLOAD &&
+ LD->getAddressingMode() == ISD::UNINDEXED &&
+ LD->getLoadedVT() == MVT::i8;
+ return false;
+}]>;
+def zextloadi16 : PatFrag<(ops node:$ptr), (ld node:$ptr), [{
+ if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N))
+ return LD->getExtensionType() == ISD::ZEXTLOAD &&
+ LD->getAddressingMode() == ISD::UNINDEXED &&
+ LD->getLoadedVT() == MVT::i16;
+ return false;
+}]>;
+def zextloadi32 : PatFrag<(ops node:$ptr), (ld node:$ptr), [{
+ if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N))
+ return LD->getExtensionType() == ISD::ZEXTLOAD &&
+ LD->getAddressingMode() == ISD::UNINDEXED &&
+ LD->getLoadedVT() == MVT::i32;
+ return false;
+}]>;
+
+// store fragments.
+def store : PatFrag<(ops node:$val, node:$ptr),
+ (st node:$val, node:$ptr), [{
+ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N))
+ return !ST->isTruncatingStore() &&
+ ST->getAddressingMode() == ISD::UNINDEXED;
+ return false;
+}]>;
+
+// truncstore fragments.
+def truncstorei1 : PatFrag<(ops node:$val, node:$ptr),
+ (st node:$val, node:$ptr), [{
+ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N))
+ return ST->isTruncatingStore() && ST->getStoredVT() == MVT::i1 &&
+ ST->getAddressingMode() == ISD::UNINDEXED;
+ return false;
+}]>;
+def truncstorei8 : PatFrag<(ops node:$val, node:$ptr),
+ (st node:$val, node:$ptr), [{
+ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N))
+ return ST->isTruncatingStore() && ST->getStoredVT() == MVT::i8 &&
+ ST->getAddressingMode() == ISD::UNINDEXED;
+ return false;
+}]>;
+def truncstorei16 : PatFrag<(ops node:$val, node:$ptr),
+ (st node:$val, node:$ptr), [{
+ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N))
+ return ST->isTruncatingStore() && ST->getStoredVT() == MVT::i16 &&
+ ST->getAddressingMode() == ISD::UNINDEXED;
+ return false;
+}]>;
+def truncstorei32 : PatFrag<(ops node:$val, node:$ptr),
+ (st node:$val, node:$ptr), [{
+ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N))
+ return ST->isTruncatingStore() && ST->getStoredVT() == MVT::i32 &&
+ ST->getAddressingMode() == ISD::UNINDEXED;
+ return false;
+}]>;
+def truncstoref32 : PatFrag<(ops node:$val, node:$ptr),
+ (st node:$val, node:$ptr), [{
+ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N))
+ return ST->isTruncatingStore() && ST->getStoredVT() == MVT::f32 &&
+ ST->getAddressingMode() == ISD::UNINDEXED;
+ return false;
+}]>;
+
+// indexed store fragments.
+def pre_store : PatFrag<(ops node:$val, node:$base, node:$offset),
+ (ist node:$val, node:$base, node:$offset), [{
+ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
+ ISD::MemIndexedMode AM = ST->getAddressingMode();
+ return (AM == ISD::PRE_INC || AM == ISD::PRE_DEC) &&
+ !ST->isTruncatingStore();
+ }
+ return false;
+}]>;
+
+def pre_truncsti1 : PatFrag<(ops node:$val, node:$base, node:$offset),
+ (ist node:$val, node:$base, node:$offset), [{
+ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
+ ISD::MemIndexedMode AM = ST->getAddressingMode();
+ return (AM == ISD::PRE_INC || AM == ISD::PRE_DEC) &&
+ ST->isTruncatingStore() && ST->getStoredVT() == MVT::i1;
+ }
+ return false;
+}]>;
+def pre_truncsti8 : PatFrag<(ops node:$val, node:$base, node:$offset),
+ (ist node:$val, node:$base, node:$offset), [{
+ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
+ ISD::MemIndexedMode AM = ST->getAddressingMode();
+ return (AM == ISD::PRE_INC || AM == ISD::PRE_DEC) &&
+ ST->isTruncatingStore() && ST->getStoredVT() == MVT::i8;
+ }
+ return false;
+}]>;
+def pre_truncsti16 : PatFrag<(ops node:$val, node:$base, node:$offset),
+ (ist node:$val, node:$base, node:$offset), [{
+ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
+ ISD::MemIndexedMode AM = ST->getAddressingMode();
+ return (AM == ISD::PRE_INC || AM == ISD::PRE_DEC) &&
+ ST->isTruncatingStore() && ST->getStoredVT() == MVT::i16;
+ }
+ return false;
+}]>;
+def pre_truncsti32 : PatFrag<(ops node:$val, node:$base, node:$offset),
+ (ist node:$val, node:$base, node:$offset), [{
+ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
+ ISD::MemIndexedMode AM = ST->getAddressingMode();
+ return (AM == ISD::PRE_INC || AM == ISD::PRE_DEC) &&
+ ST->isTruncatingStore() && ST->getStoredVT() == MVT::i32;
+ }
+ return false;
+}]>;
+def pre_truncstf32 : PatFrag<(ops node:$val, node:$base, node:$offset),
+ (ist node:$val, node:$base, node:$offset), [{
+ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
+ ISD::MemIndexedMode AM = ST->getAddressingMode();
+ return (AM == ISD::PRE_INC || AM == ISD::PRE_DEC) &&
+ ST->isTruncatingStore() && ST->getStoredVT() == MVT::f32;
+ }
+ return false;
+}]>;
+
+def post_store : PatFrag<(ops node:$val, node:$ptr, node:$offset),
+ (ist node:$val, node:$ptr, node:$offset), [{
+ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
+ ISD::MemIndexedMode AM = ST->getAddressingMode();
+ return !ST->isTruncatingStore() &&
+ (AM == ISD::POST_INC || AM == ISD::POST_DEC);
+ }
+ return false;
+}]>;
+
+def post_truncsti1 : PatFrag<(ops node:$val, node:$base, node:$offset),
+ (ist node:$val, node:$base, node:$offset), [{
+ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
+ ISD::MemIndexedMode AM = ST->getAddressingMode();
+ return (AM == ISD::POST_INC || AM == ISD::POST_DEC) &&
+ ST->isTruncatingStore() && ST->getStoredVT() == MVT::i1;
+ }
+ return false;
+}]>;
+def post_truncsti8 : PatFrag<(ops node:$val, node:$base, node:$offset),
+ (ist node:$val, node:$base, node:$offset), [{
+ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
+ ISD::MemIndexedMode AM = ST->getAddressingMode();
+ return (AM == ISD::POST_INC || AM == ISD::POST_DEC) &&
+ ST->isTruncatingStore() && ST->getStoredVT() == MVT::i8;
+ }
+ return false;
+}]>;
+def post_truncsti16 : PatFrag<(ops node:$val, node:$base, node:$offset),
+ (ist node:$val, node:$base, node:$offset), [{
+ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
+ ISD::MemIndexedMode AM = ST->getAddressingMode();
+ return (AM == ISD::POST_INC || AM == ISD::POST_DEC) &&
+ ST->isTruncatingStore() && ST->getStoredVT() == MVT::i16;
+ }
+ return false;
+}]>;
+def post_truncsti32 : PatFrag<(ops node:$val, node:$base, node:$offset),
+ (ist node:$val, node:$base, node:$offset), [{
+ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
+ ISD::MemIndexedMode AM = ST->getAddressingMode();
+ return (AM == ISD::POST_INC || AM == ISD::POST_DEC) &&
+ ST->isTruncatingStore() && ST->getStoredVT() == MVT::i32;
+ }
+ return false;
+}]>;
+def post_truncstf32 : PatFrag<(ops node:$val, node:$base, node:$offset),
+ (ist node:$val, node:$base, node:$offset), [{
+ if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
+ ISD::MemIndexedMode AM = ST->getAddressingMode();
+ return (AM == ISD::POST_INC || AM == ISD::POST_DEC) &&
+ ST->isTruncatingStore() && ST->getStoredVT() == MVT::f32;
+ }
+ return false;
+}]>;
// setcc convenience fragments.
def setoeq : PatFrag<(ops node:$lhs, node:$rhs),
//
class Pattern<dag patternToMatch, list<dag> resultInstrs> {
- dag PatternToMatch = patternToMatch;
- list<dag> ResultInstrs = resultInstrs;
- list<Predicate> Predicates = []; // See class Instruction in Target.td.
+ 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
// 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 = []> {
+class ComplexPattern<ValueType ty, int numops, string fn,
+ list<SDNode> roots = [], list<SDNodeProperty> props = []> {
ValueType Ty = ty;
int NumOperands = numops;
string SelectFunc = fn;
list<SDNode> RootNodes = roots;
+ list<SDNodeProperty> Properties = props;
}
//===----------------------------------------------------------------------===//