Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1 | //===- TargetSelectionDAG.td - Common code for DAG isels ---*- tablegen -*-===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file defines the target-independent interfaces used by SelectionDAG |
| 11 | // instruction selection generators. |
| 12 | // |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
| 15 | //===----------------------------------------------------------------------===// |
| 16 | // Selection DAG Type Constraint definitions. |
| 17 | // |
| 18 | // Note that the semantics of these constraints are hard coded into tblgen. To |
| 19 | // modify or add constraints, you have to hack tblgen. |
| 20 | // |
| 21 | |
| 22 | class SDTypeConstraint<int opnum> { |
| 23 | int OperandNum = opnum; |
| 24 | } |
| 25 | |
| 26 | // SDTCisVT - The specified operand has exactly this VT. |
| 27 | class SDTCisVT<int OpNum, ValueType vt> : SDTypeConstraint<OpNum> { |
| 28 | ValueType VT = vt; |
| 29 | } |
| 30 | |
| 31 | class SDTCisPtrTy<int OpNum> : SDTypeConstraint<OpNum>; |
| 32 | |
| 33 | // SDTCisInt - The specified operand has integer type. |
| 34 | class SDTCisInt<int OpNum> : SDTypeConstraint<OpNum>; |
| 35 | |
| 36 | // SDTCisFP - The specified operand has floating-point type. |
| 37 | class SDTCisFP<int OpNum> : SDTypeConstraint<OpNum>; |
| 38 | |
| 39 | // SDTCisVec - The specified operand has a vector type. |
| 40 | class SDTCisVec<int OpNum> : SDTypeConstraint<OpNum>; |
| 41 | |
| 42 | // SDTCisSameAs - The two specified operands have identical types. |
| 43 | class SDTCisSameAs<int OpNum, int OtherOp> : SDTypeConstraint<OpNum> { |
| 44 | int OtherOperandNum = OtherOp; |
| 45 | } |
| 46 | |
| 47 | // SDTCisVTSmallerThanOp - The specified operand is a VT SDNode, and its type is |
| 48 | // smaller than the 'Other' operand. |
| 49 | class SDTCisVTSmallerThanOp<int OpNum, int OtherOp> : SDTypeConstraint<OpNum> { |
| 50 | int OtherOperandNum = OtherOp; |
| 51 | } |
| 52 | |
| 53 | class SDTCisOpSmallerThanOp<int SmallOp, int BigOp> : SDTypeConstraint<SmallOp>{ |
| 54 | int BigOperandNum = BigOp; |
| 55 | } |
| 56 | |
| 57 | /// SDTCisEltOfVec - This indicates that ThisOp is a scalar type of the same |
| 58 | /// type as the element type of OtherOp, which is a vector type. |
| 59 | class SDTCisEltOfVec<int ThisOp, int OtherOp> |
| 60 | : SDTypeConstraint<ThisOp> { |
| 61 | int OtherOpNum = OtherOp; |
| 62 | } |
| 63 | |
| 64 | /// SDTCisSubVecOfVec - This indicates that ThisOp is a vector type |
| 65 | /// with length less that of OtherOp, which is a vector type. |
| 66 | class SDTCisSubVecOfVec<int ThisOp, int OtherOp> |
| 67 | : SDTypeConstraint<ThisOp> { |
| 68 | int OtherOpNum = OtherOp; |
| 69 | } |
| 70 | |
| 71 | // SDTCVecEltisVT - The specified operand is vector type with element type |
| 72 | // of VT. |
| 73 | class SDTCVecEltisVT<int OpNum, ValueType vt> : SDTypeConstraint<OpNum> { |
| 74 | ValueType VT = vt; |
| 75 | } |
| 76 | |
| 77 | // SDTCisSameNumEltsAs - The two specified operands have identical number |
| 78 | // of elements. |
| 79 | class SDTCisSameNumEltsAs<int OpNum, int OtherOp> : SDTypeConstraint<OpNum> { |
| 80 | int OtherOperandNum = OtherOp; |
| 81 | } |
| 82 | |
| 83 | // SDTCisSameSizeAs - The two specified operands have identical size. |
| 84 | class SDTCisSameSizeAs<int OpNum, int OtherOp> : SDTypeConstraint<OpNum> { |
| 85 | int OtherOperandNum = OtherOp; |
| 86 | } |
| 87 | |
| 88 | //===----------------------------------------------------------------------===// |
| 89 | // Selection DAG Type Profile definitions. |
| 90 | // |
| 91 | // These use the constraints defined above to describe the type requirements of |
| 92 | // the various nodes. These are not hard coded into tblgen, allowing targets to |
| 93 | // add their own if needed. |
| 94 | // |
| 95 | |
| 96 | // SDTypeProfile - This profile describes the type requirements of a Selection |
| 97 | // DAG node. |
| 98 | class SDTypeProfile<int numresults, int numoperands, |
| 99 | list<SDTypeConstraint> constraints> { |
| 100 | int NumResults = numresults; |
| 101 | int NumOperands = numoperands; |
| 102 | list<SDTypeConstraint> Constraints = constraints; |
| 103 | } |
| 104 | |
| 105 | // Builtin profiles. |
| 106 | def SDTIntLeaf: SDTypeProfile<1, 0, [SDTCisInt<0>]>; // for 'imm'. |
| 107 | def SDTFPLeaf : SDTypeProfile<1, 0, [SDTCisFP<0>]>; // for 'fpimm'. |
| 108 | def SDTPtrLeaf: SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; // for '&g'. |
| 109 | def SDTOther : SDTypeProfile<1, 0, [SDTCisVT<0, OtherVT>]>; // for 'vt'. |
| 110 | def SDTUNDEF : SDTypeProfile<1, 0, []>; // for 'undef'. |
| 111 | def SDTUnaryOp : SDTypeProfile<1, 1, []>; // for bitconvert. |
| 112 | |
| 113 | def SDTIntBinOp : SDTypeProfile<1, 2, [ // add, and, or, xor, udiv, etc. |
| 114 | SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisInt<0> |
| 115 | ]>; |
| 116 | def SDTIntShiftOp : SDTypeProfile<1, 2, [ // shl, sra, srl |
| 117 | SDTCisSameAs<0, 1>, SDTCisInt<0>, SDTCisInt<2> |
| 118 | ]>; |
| 119 | def SDTIntSatNoShOp : SDTypeProfile<1, 2, [ // ssat with no shift |
| 120 | SDTCisSameAs<0, 1>, SDTCisInt<2> |
| 121 | ]>; |
| 122 | def SDTIntBinHiLoOp : SDTypeProfile<2, 2, [ // mulhi, mullo, sdivrem, udivrem |
| 123 | SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>,SDTCisInt<0> |
| 124 | ]>; |
| 125 | |
| 126 | def SDTFPBinOp : SDTypeProfile<1, 2, [ // fadd, fmul, etc. |
| 127 | SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisFP<0> |
| 128 | ]>; |
| 129 | def SDTFPSignOp : SDTypeProfile<1, 2, [ // fcopysign. |
| 130 | SDTCisSameAs<0, 1>, SDTCisFP<0>, SDTCisFP<2> |
| 131 | ]>; |
| 132 | def SDTFPTernaryOp : SDTypeProfile<1, 3, [ // fmadd, fnmsub, etc. |
| 133 | SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>, SDTCisFP<0> |
| 134 | ]>; |
| 135 | def SDTIntUnaryOp : SDTypeProfile<1, 1, [ // ctlz, cttz |
| 136 | SDTCisSameAs<0, 1>, SDTCisInt<0> |
| 137 | ]>; |
| 138 | def SDTIntExtendOp : SDTypeProfile<1, 1, [ // sext, zext, anyext |
| 139 | SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<1, 0>, SDTCisSameNumEltsAs<0, 1> |
| 140 | ]>; |
| 141 | def SDTIntTruncOp : SDTypeProfile<1, 1, [ // trunc |
| 142 | SDTCisInt<0>, SDTCisInt<1>, SDTCisOpSmallerThanOp<0, 1>, SDTCisSameNumEltsAs<0, 1> |
| 143 | ]>; |
| 144 | def SDTFPUnaryOp : SDTypeProfile<1, 1, [ // fneg, fsqrt, etc |
| 145 | SDTCisSameAs<0, 1>, SDTCisFP<0> |
| 146 | ]>; |
| 147 | def SDTFPRoundOp : SDTypeProfile<1, 1, [ // fround |
| 148 | SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<0, 1>, SDTCisSameNumEltsAs<0, 1> |
| 149 | ]>; |
| 150 | def SDTFPExtendOp : SDTypeProfile<1, 1, [ // fextend |
| 151 | SDTCisFP<0>, SDTCisFP<1>, SDTCisOpSmallerThanOp<1, 0>, SDTCisSameNumEltsAs<0, 1> |
| 152 | ]>; |
| 153 | def SDTIntToFPOp : SDTypeProfile<1, 1, [ // [su]int_to_fp |
| 154 | SDTCisFP<0>, SDTCisInt<1>, SDTCisSameNumEltsAs<0, 1> |
| 155 | ]>; |
| 156 | def SDTFPToIntOp : SDTypeProfile<1, 1, [ // fp_to_[su]int |
| 157 | SDTCisInt<0>, SDTCisFP<1>, SDTCisSameNumEltsAs<0, 1> |
| 158 | ]>; |
| 159 | def SDTExtInreg : SDTypeProfile<1, 2, [ // sext_inreg |
| 160 | SDTCisSameAs<0, 1>, SDTCisInt<0>, SDTCisVT<2, OtherVT>, |
| 161 | SDTCisVTSmallerThanOp<2, 1> |
| 162 | ]>; |
| 163 | def SDTExtInvec : SDTypeProfile<1, 1, [ // sext_invec |
| 164 | SDTCisInt<0>, SDTCisVec<0>, SDTCisInt<1>, SDTCisVec<1>, |
| 165 | SDTCisOpSmallerThanOp<1, 0>, SDTCisSameSizeAs<0,1> |
| 166 | ]>; |
| 167 | |
| 168 | def SDTSetCC : SDTypeProfile<1, 3, [ // setcc |
| 169 | SDTCisInt<0>, SDTCisSameAs<1, 2>, SDTCisVT<3, OtherVT> |
| 170 | ]>; |
| 171 | |
| 172 | def SDTSelect : SDTypeProfile<1, 3, [ // select |
| 173 | SDTCisInt<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3> |
| 174 | ]>; |
| 175 | |
| 176 | def SDTVSelect : SDTypeProfile<1, 3, [ // vselect |
| 177 | SDTCisVec<0>, SDTCisInt<1>, SDTCisSameAs<0, 2>, SDTCisSameAs<2, 3>, SDTCisSameNumEltsAs<0, 1> |
| 178 | ]>; |
| 179 | |
| 180 | def SDTSelectCC : SDTypeProfile<1, 5, [ // select_cc |
| 181 | SDTCisSameAs<1, 2>, SDTCisSameAs<3, 4>, SDTCisSameAs<0, 3>, |
| 182 | SDTCisVT<5, OtherVT> |
| 183 | ]>; |
| 184 | |
| 185 | def SDTBr : SDTypeProfile<0, 1, [ // br |
| 186 | SDTCisVT<0, OtherVT> |
| 187 | ]>; |
| 188 | |
| 189 | def SDTBrCC : SDTypeProfile<0, 4, [ // brcc |
| 190 | SDTCisVT<0, OtherVT>, SDTCisSameAs<1, 2>, SDTCisVT<3, OtherVT> |
| 191 | ]>; |
| 192 | |
| 193 | def SDTBrcond : SDTypeProfile<0, 2, [ // brcond |
| 194 | SDTCisInt<0>, SDTCisVT<1, OtherVT> |
| 195 | ]>; |
| 196 | |
| 197 | def SDTBrind : SDTypeProfile<0, 1, [ // brind |
| 198 | SDTCisPtrTy<0> |
| 199 | ]>; |
| 200 | |
| 201 | def SDTCatchret : SDTypeProfile<0, 2, [ // catchret |
| 202 | SDTCisVT<0, OtherVT>, SDTCisVT<1, OtherVT> |
| 203 | ]>; |
| 204 | |
| 205 | def SDTNone : SDTypeProfile<0, 0, []>; // ret, trap |
| 206 | |
| 207 | def SDTLoad : SDTypeProfile<1, 1, [ // load |
| 208 | SDTCisPtrTy<1> |
| 209 | ]>; |
| 210 | |
| 211 | def SDTStore : SDTypeProfile<0, 2, [ // store |
| 212 | SDTCisPtrTy<1> |
| 213 | ]>; |
| 214 | |
| 215 | def SDTIStore : SDTypeProfile<1, 3, [ // indexed store |
| 216 | SDTCisSameAs<0, 2>, SDTCisPtrTy<0>, SDTCisPtrTy<3> |
| 217 | ]>; |
| 218 | |
| 219 | def SDTMaskedStore: SDTypeProfile<0, 3, [ // masked store |
Andrew Scull | 0372a57 | 2018-11-16 15:47:06 +0000 | [diff] [blame] | 220 | SDTCisVec<0>, SDTCisPtrTy<1>, SDTCisVec<2>, SDTCisSameNumEltsAs<0, 2> |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 221 | ]>; |
| 222 | |
| 223 | def SDTMaskedLoad: SDTypeProfile<1, 3, [ // masked load |
| 224 | SDTCisVec<0>, SDTCisPtrTy<1>, SDTCisVec<2>, SDTCisSameAs<0, 3>, |
| 225 | SDTCisSameNumEltsAs<0, 2> |
| 226 | ]>; |
| 227 | |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 228 | def SDTVecShuffle : SDTypeProfile<1, 2, [ |
| 229 | SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2> |
| 230 | ]>; |
| 231 | def SDTVecExtract : SDTypeProfile<1, 2, [ // vector extract |
| 232 | SDTCisEltOfVec<0, 1>, SDTCisPtrTy<2> |
| 233 | ]>; |
| 234 | def SDTVecInsert : SDTypeProfile<1, 3, [ // vector insert |
| 235 | SDTCisEltOfVec<2, 1>, SDTCisSameAs<0, 1>, SDTCisPtrTy<3> |
| 236 | ]>; |
| 237 | |
| 238 | def SDTSubVecExtract : SDTypeProfile<1, 2, [// subvector extract |
| 239 | SDTCisSubVecOfVec<0,1>, SDTCisInt<2> |
| 240 | ]>; |
| 241 | def SDTSubVecInsert : SDTypeProfile<1, 3, [ // subvector insert |
| 242 | SDTCisSubVecOfVec<2, 1>, SDTCisSameAs<0,1>, SDTCisInt<3> |
| 243 | ]>; |
| 244 | |
| 245 | def SDTPrefetch : SDTypeProfile<0, 4, [ // prefetch |
| 246 | SDTCisPtrTy<0>, SDTCisSameAs<1, 2>, SDTCisSameAs<1, 3>, SDTCisInt<1> |
| 247 | ]>; |
| 248 | |
| 249 | def SDTMemBarrier : SDTypeProfile<0, 5, [ // memory barrier |
| 250 | SDTCisSameAs<0,1>, SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisSameAs<0,4>, |
| 251 | SDTCisInt<0> |
| 252 | ]>; |
| 253 | def SDTAtomicFence : SDTypeProfile<0, 2, [ |
| 254 | SDTCisSameAs<0,1>, SDTCisPtrTy<0> |
| 255 | ]>; |
| 256 | def SDTAtomic3 : SDTypeProfile<1, 3, [ |
| 257 | SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisInt<0>, SDTCisPtrTy<1> |
| 258 | ]>; |
| 259 | def SDTAtomic2 : SDTypeProfile<1, 2, [ |
| 260 | SDTCisSameAs<0,2>, SDTCisInt<0>, SDTCisPtrTy<1> |
| 261 | ]>; |
| 262 | def SDTAtomicStore : SDTypeProfile<0, 2, [ |
| 263 | SDTCisPtrTy<0>, SDTCisInt<1> |
| 264 | ]>; |
| 265 | def SDTAtomicLoad : SDTypeProfile<1, 1, [ |
| 266 | SDTCisInt<0>, SDTCisPtrTy<1> |
| 267 | ]>; |
| 268 | |
| 269 | def SDTConvertOp : SDTypeProfile<1, 5, [ //cvtss, su, us, uu, ff, fs, fu, sf, su |
| 270 | SDTCisVT<2, OtherVT>, SDTCisVT<3, OtherVT>, SDTCisPtrTy<4>, SDTCisPtrTy<5> |
| 271 | ]>; |
| 272 | |
| 273 | class SDCallSeqStart<list<SDTypeConstraint> constraints> : |
| 274 | SDTypeProfile<0, 2, constraints>; |
| 275 | class SDCallSeqEnd<list<SDTypeConstraint> constraints> : |
| 276 | SDTypeProfile<0, 2, constraints>; |
| 277 | |
| 278 | //===----------------------------------------------------------------------===// |
| 279 | // Selection DAG Node definitions. |
| 280 | // |
| 281 | class SDNode<string opcode, SDTypeProfile typeprof, |
| 282 | list<SDNodeProperty> props = [], string sdclass = "SDNode"> |
| 283 | : SDPatternOperator { |
| 284 | string Opcode = opcode; |
| 285 | string SDClass = sdclass; |
| 286 | let Properties = props; |
| 287 | SDTypeProfile TypeProfile = typeprof; |
| 288 | } |
| 289 | |
| 290 | // Special TableGen-recognized dag nodes |
| 291 | def set; |
| 292 | def implicit; |
| 293 | def node; |
| 294 | def srcvalue; |
| 295 | |
| 296 | def imm : SDNode<"ISD::Constant" , SDTIntLeaf , [], "ConstantSDNode">; |
| 297 | def timm : SDNode<"ISD::TargetConstant",SDTIntLeaf, [], "ConstantSDNode">; |
| 298 | def fpimm : SDNode<"ISD::ConstantFP", SDTFPLeaf , [], "ConstantFPSDNode">; |
| 299 | def vt : SDNode<"ISD::VALUETYPE" , SDTOther , [], "VTSDNode">; |
| 300 | def bb : SDNode<"ISD::BasicBlock", SDTOther , [], "BasicBlockSDNode">; |
| 301 | def cond : SDNode<"ISD::CONDCODE" , SDTOther , [], "CondCodeSDNode">; |
| 302 | def undef : SDNode<"ISD::UNDEF" , SDTUNDEF , []>; |
| 303 | def globaladdr : SDNode<"ISD::GlobalAddress", SDTPtrLeaf, [], |
| 304 | "GlobalAddressSDNode">; |
| 305 | def tglobaladdr : SDNode<"ISD::TargetGlobalAddress", SDTPtrLeaf, [], |
| 306 | "GlobalAddressSDNode">; |
| 307 | def globaltlsaddr : SDNode<"ISD::GlobalTLSAddress", SDTPtrLeaf, [], |
| 308 | "GlobalAddressSDNode">; |
| 309 | def tglobaltlsaddr : SDNode<"ISD::TargetGlobalTLSAddress", SDTPtrLeaf, [], |
| 310 | "GlobalAddressSDNode">; |
| 311 | def constpool : SDNode<"ISD::ConstantPool", SDTPtrLeaf, [], |
| 312 | "ConstantPoolSDNode">; |
| 313 | def tconstpool : SDNode<"ISD::TargetConstantPool", SDTPtrLeaf, [], |
| 314 | "ConstantPoolSDNode">; |
| 315 | def jumptable : SDNode<"ISD::JumpTable", SDTPtrLeaf, [], |
| 316 | "JumpTableSDNode">; |
| 317 | def tjumptable : SDNode<"ISD::TargetJumpTable", SDTPtrLeaf, [], |
| 318 | "JumpTableSDNode">; |
| 319 | def frameindex : SDNode<"ISD::FrameIndex", SDTPtrLeaf, [], |
| 320 | "FrameIndexSDNode">; |
| 321 | def tframeindex : SDNode<"ISD::TargetFrameIndex", SDTPtrLeaf, [], |
| 322 | "FrameIndexSDNode">; |
| 323 | def externalsym : SDNode<"ISD::ExternalSymbol", SDTPtrLeaf, [], |
| 324 | "ExternalSymbolSDNode">; |
| 325 | def texternalsym: SDNode<"ISD::TargetExternalSymbol", SDTPtrLeaf, [], |
| 326 | "ExternalSymbolSDNode">; |
| 327 | def mcsym: SDNode<"ISD::MCSymbol", SDTPtrLeaf, [], "MCSymbolSDNode">; |
| 328 | def blockaddress : SDNode<"ISD::BlockAddress", SDTPtrLeaf, [], |
| 329 | "BlockAddressSDNode">; |
| 330 | def tblockaddress: SDNode<"ISD::TargetBlockAddress", SDTPtrLeaf, [], |
| 331 | "BlockAddressSDNode">; |
| 332 | |
| 333 | def add : SDNode<"ISD::ADD" , SDTIntBinOp , |
| 334 | [SDNPCommutative, SDNPAssociative]>; |
| 335 | def sub : SDNode<"ISD::SUB" , SDTIntBinOp>; |
| 336 | def mul : SDNode<"ISD::MUL" , SDTIntBinOp, |
| 337 | [SDNPCommutative, SDNPAssociative]>; |
| 338 | def mulhs : SDNode<"ISD::MULHS" , SDTIntBinOp, [SDNPCommutative]>; |
| 339 | def mulhu : SDNode<"ISD::MULHU" , SDTIntBinOp, [SDNPCommutative]>; |
| 340 | def smullohi : SDNode<"ISD::SMUL_LOHI" , SDTIntBinHiLoOp, [SDNPCommutative]>; |
| 341 | def umullohi : SDNode<"ISD::UMUL_LOHI" , SDTIntBinHiLoOp, [SDNPCommutative]>; |
| 342 | def sdiv : SDNode<"ISD::SDIV" , SDTIntBinOp>; |
| 343 | def udiv : SDNode<"ISD::UDIV" , SDTIntBinOp>; |
| 344 | def srem : SDNode<"ISD::SREM" , SDTIntBinOp>; |
| 345 | def urem : SDNode<"ISD::UREM" , SDTIntBinOp>; |
| 346 | def sdivrem : SDNode<"ISD::SDIVREM" , SDTIntBinHiLoOp>; |
| 347 | def udivrem : SDNode<"ISD::UDIVREM" , SDTIntBinHiLoOp>; |
| 348 | def srl : SDNode<"ISD::SRL" , SDTIntShiftOp>; |
| 349 | def sra : SDNode<"ISD::SRA" , SDTIntShiftOp>; |
| 350 | def shl : SDNode<"ISD::SHL" , SDTIntShiftOp>; |
| 351 | def rotl : SDNode<"ISD::ROTL" , SDTIntShiftOp>; |
| 352 | def rotr : SDNode<"ISD::ROTR" , SDTIntShiftOp>; |
| 353 | def and : SDNode<"ISD::AND" , SDTIntBinOp, |
| 354 | [SDNPCommutative, SDNPAssociative]>; |
| 355 | def or : SDNode<"ISD::OR" , SDTIntBinOp, |
| 356 | [SDNPCommutative, SDNPAssociative]>; |
| 357 | def xor : SDNode<"ISD::XOR" , SDTIntBinOp, |
| 358 | [SDNPCommutative, SDNPAssociative]>; |
| 359 | def addc : SDNode<"ISD::ADDC" , SDTIntBinOp, |
| 360 | [SDNPCommutative, SDNPOutGlue]>; |
| 361 | def adde : SDNode<"ISD::ADDE" , SDTIntBinOp, |
| 362 | [SDNPCommutative, SDNPOutGlue, SDNPInGlue]>; |
| 363 | def subc : SDNode<"ISD::SUBC" , SDTIntBinOp, |
| 364 | [SDNPOutGlue]>; |
| 365 | def sube : SDNode<"ISD::SUBE" , SDTIntBinOp, |
| 366 | [SDNPOutGlue, SDNPInGlue]>; |
| 367 | def smin : SDNode<"ISD::SMIN" , SDTIntBinOp, |
| 368 | [SDNPCommutative, SDNPAssociative]>; |
| 369 | def smax : SDNode<"ISD::SMAX" , SDTIntBinOp, |
| 370 | [SDNPCommutative, SDNPAssociative]>; |
| 371 | def umin : SDNode<"ISD::UMIN" , SDTIntBinOp, |
| 372 | [SDNPCommutative, SDNPAssociative]>; |
| 373 | def umax : SDNode<"ISD::UMAX" , SDTIntBinOp, |
| 374 | [SDNPCommutative, SDNPAssociative]>; |
| 375 | |
| 376 | def sext_inreg : SDNode<"ISD::SIGN_EXTEND_INREG", SDTExtInreg>; |
| 377 | def sext_invec : SDNode<"ISD::SIGN_EXTEND_VECTOR_INREG", SDTExtInvec>; |
| 378 | def zext_invec : SDNode<"ISD::ZERO_EXTEND_VECTOR_INREG", SDTExtInvec>; |
| 379 | |
| 380 | def abs : SDNode<"ISD::ABS" , SDTIntUnaryOp>; |
| 381 | def bitreverse : SDNode<"ISD::BITREVERSE" , SDTIntUnaryOp>; |
| 382 | def bswap : SDNode<"ISD::BSWAP" , SDTIntUnaryOp>; |
| 383 | def ctlz : SDNode<"ISD::CTLZ" , SDTIntUnaryOp>; |
| 384 | def cttz : SDNode<"ISD::CTTZ" , SDTIntUnaryOp>; |
| 385 | def ctpop : SDNode<"ISD::CTPOP" , SDTIntUnaryOp>; |
| 386 | def ctlz_zero_undef : SDNode<"ISD::CTLZ_ZERO_UNDEF", SDTIntUnaryOp>; |
| 387 | def cttz_zero_undef : SDNode<"ISD::CTTZ_ZERO_UNDEF", SDTIntUnaryOp>; |
| 388 | def sext : SDNode<"ISD::SIGN_EXTEND", SDTIntExtendOp>; |
| 389 | def zext : SDNode<"ISD::ZERO_EXTEND", SDTIntExtendOp>; |
| 390 | def anyext : SDNode<"ISD::ANY_EXTEND" , SDTIntExtendOp>; |
| 391 | def trunc : SDNode<"ISD::TRUNCATE" , SDTIntTruncOp>; |
| 392 | def bitconvert : SDNode<"ISD::BITCAST" , SDTUnaryOp>; |
| 393 | def addrspacecast : SDNode<"ISD::ADDRSPACECAST", SDTUnaryOp>; |
| 394 | def extractelt : SDNode<"ISD::EXTRACT_VECTOR_ELT", SDTVecExtract>; |
| 395 | def insertelt : SDNode<"ISD::INSERT_VECTOR_ELT", SDTVecInsert>; |
| 396 | |
| 397 | def fadd : SDNode<"ISD::FADD" , SDTFPBinOp, [SDNPCommutative]>; |
| 398 | def fsub : SDNode<"ISD::FSUB" , SDTFPBinOp>; |
| 399 | def fmul : SDNode<"ISD::FMUL" , SDTFPBinOp, [SDNPCommutative]>; |
| 400 | def fdiv : SDNode<"ISD::FDIV" , SDTFPBinOp>; |
| 401 | def frem : SDNode<"ISD::FREM" , SDTFPBinOp>; |
| 402 | def fma : SDNode<"ISD::FMA" , SDTFPTernaryOp>; |
| 403 | def fmad : SDNode<"ISD::FMAD" , SDTFPTernaryOp>; |
| 404 | def fabs : SDNode<"ISD::FABS" , SDTFPUnaryOp>; |
| 405 | def fminnum : SDNode<"ISD::FMINNUM" , SDTFPBinOp, |
| 406 | [SDNPCommutative, SDNPAssociative]>; |
| 407 | def fmaxnum : SDNode<"ISD::FMAXNUM" , SDTFPBinOp, |
| 408 | [SDNPCommutative, SDNPAssociative]>; |
| 409 | def fminnan : SDNode<"ISD::FMINNAN" , SDTFPBinOp>; |
| 410 | def fmaxnan : SDNode<"ISD::FMAXNAN" , SDTFPBinOp>; |
| 411 | def fgetsign : SDNode<"ISD::FGETSIGN" , SDTFPToIntOp>; |
| 412 | def fcanonicalize : SDNode<"ISD::FCANONICALIZE", SDTFPUnaryOp>; |
| 413 | def fneg : SDNode<"ISD::FNEG" , SDTFPUnaryOp>; |
| 414 | def fsqrt : SDNode<"ISD::FSQRT" , SDTFPUnaryOp>; |
| 415 | def fsin : SDNode<"ISD::FSIN" , SDTFPUnaryOp>; |
| 416 | def fcos : SDNode<"ISD::FCOS" , SDTFPUnaryOp>; |
| 417 | def fexp2 : SDNode<"ISD::FEXP2" , SDTFPUnaryOp>; |
| 418 | def fpow : SDNode<"ISD::FPOW" , SDTFPBinOp>; |
| 419 | def flog2 : SDNode<"ISD::FLOG2" , SDTFPUnaryOp>; |
| 420 | def frint : SDNode<"ISD::FRINT" , SDTFPUnaryOp>; |
| 421 | def ftrunc : SDNode<"ISD::FTRUNC" , SDTFPUnaryOp>; |
| 422 | def fceil : SDNode<"ISD::FCEIL" , SDTFPUnaryOp>; |
| 423 | def ffloor : SDNode<"ISD::FFLOOR" , SDTFPUnaryOp>; |
| 424 | def fnearbyint : SDNode<"ISD::FNEARBYINT" , SDTFPUnaryOp>; |
| 425 | def fround : SDNode<"ISD::FROUND" , SDTFPUnaryOp>; |
| 426 | |
| 427 | def fpround : SDNode<"ISD::FP_ROUND" , SDTFPRoundOp>; |
| 428 | def fpextend : SDNode<"ISD::FP_EXTEND" , SDTFPExtendOp>; |
| 429 | def fcopysign : SDNode<"ISD::FCOPYSIGN" , SDTFPSignOp>; |
| 430 | |
| 431 | def sint_to_fp : SDNode<"ISD::SINT_TO_FP" , SDTIntToFPOp>; |
| 432 | def uint_to_fp : SDNode<"ISD::UINT_TO_FP" , SDTIntToFPOp>; |
| 433 | def fp_to_sint : SDNode<"ISD::FP_TO_SINT" , SDTFPToIntOp>; |
| 434 | def fp_to_uint : SDNode<"ISD::FP_TO_UINT" , SDTFPToIntOp>; |
| 435 | def f16_to_fp : SDNode<"ISD::FP16_TO_FP" , SDTIntToFPOp>; |
| 436 | def fp_to_f16 : SDNode<"ISD::FP_TO_FP16" , SDTFPToIntOp>; |
| 437 | |
| 438 | def setcc : SDNode<"ISD::SETCC" , SDTSetCC>; |
| 439 | def select : SDNode<"ISD::SELECT" , SDTSelect>; |
| 440 | def vselect : SDNode<"ISD::VSELECT" , SDTVSelect>; |
| 441 | def selectcc : SDNode<"ISD::SELECT_CC" , SDTSelectCC>; |
| 442 | |
| 443 | def brcc : SDNode<"ISD::BR_CC" , SDTBrCC, [SDNPHasChain]>; |
| 444 | def brcond : SDNode<"ISD::BRCOND" , SDTBrcond, [SDNPHasChain]>; |
| 445 | def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>; |
| 446 | def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>; |
| 447 | def catchret : SDNode<"ISD::CATCHRET" , SDTCatchret, |
| 448 | [SDNPHasChain, SDNPSideEffect]>; |
| 449 | def cleanupret : SDNode<"ISD::CLEANUPRET" , SDTNone, [SDNPHasChain]>; |
| 450 | def catchpad : SDNode<"ISD::CATCHPAD" , SDTNone, |
| 451 | [SDNPHasChain, SDNPSideEffect]>; |
| 452 | |
| 453 | def trap : SDNode<"ISD::TRAP" , SDTNone, |
| 454 | [SDNPHasChain, SDNPSideEffect]>; |
| 455 | def debugtrap : SDNode<"ISD::DEBUGTRAP" , SDTNone, |
| 456 | [SDNPHasChain, SDNPSideEffect]>; |
| 457 | |
| 458 | def prefetch : SDNode<"ISD::PREFETCH" , SDTPrefetch, |
| 459 | [SDNPHasChain, SDNPMayLoad, SDNPMayStore, |
| 460 | SDNPMemOperand]>; |
| 461 | |
| 462 | def readcyclecounter : SDNode<"ISD::READCYCLECOUNTER", SDTIntLeaf, |
| 463 | [SDNPHasChain, SDNPSideEffect]>; |
| 464 | |
| 465 | def atomic_fence : SDNode<"ISD::ATOMIC_FENCE" , SDTAtomicFence, |
| 466 | [SDNPHasChain, SDNPSideEffect]>; |
| 467 | |
| 468 | def atomic_cmp_swap : SDNode<"ISD::ATOMIC_CMP_SWAP" , SDTAtomic3, |
| 469 | [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; |
| 470 | def atomic_load_add : SDNode<"ISD::ATOMIC_LOAD_ADD" , SDTAtomic2, |
| 471 | [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; |
| 472 | def atomic_swap : SDNode<"ISD::ATOMIC_SWAP", SDTAtomic2, |
| 473 | [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; |
| 474 | def atomic_load_sub : SDNode<"ISD::ATOMIC_LOAD_SUB" , SDTAtomic2, |
| 475 | [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; |
| 476 | def atomic_load_and : SDNode<"ISD::ATOMIC_LOAD_AND" , SDTAtomic2, |
| 477 | [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; |
| 478 | def atomic_load_clr : SDNode<"ISD::ATOMIC_LOAD_CLR" , SDTAtomic2, |
| 479 | [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; |
| 480 | def atomic_load_or : SDNode<"ISD::ATOMIC_LOAD_OR" , SDTAtomic2, |
| 481 | [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; |
| 482 | def atomic_load_xor : SDNode<"ISD::ATOMIC_LOAD_XOR" , SDTAtomic2, |
| 483 | [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; |
| 484 | def atomic_load_nand: SDNode<"ISD::ATOMIC_LOAD_NAND", SDTAtomic2, |
| 485 | [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; |
| 486 | def atomic_load_min : SDNode<"ISD::ATOMIC_LOAD_MIN", SDTAtomic2, |
| 487 | [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; |
| 488 | def atomic_load_max : SDNode<"ISD::ATOMIC_LOAD_MAX", SDTAtomic2, |
| 489 | [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; |
| 490 | def atomic_load_umin : SDNode<"ISD::ATOMIC_LOAD_UMIN", SDTAtomic2, |
| 491 | [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; |
| 492 | def atomic_load_umax : SDNode<"ISD::ATOMIC_LOAD_UMAX", SDTAtomic2, |
| 493 | [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; |
| 494 | def atomic_load : SDNode<"ISD::ATOMIC_LOAD", SDTAtomicLoad, |
| 495 | [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; |
| 496 | def atomic_store : SDNode<"ISD::ATOMIC_STORE", SDTAtomicStore, |
| 497 | [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; |
| 498 | |
| 499 | def masked_store : SDNode<"ISD::MSTORE", SDTMaskedStore, |
| 500 | [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; |
| 501 | def masked_load : SDNode<"ISD::MLOAD", SDTMaskedLoad, |
| 502 | [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 503 | |
| 504 | // Do not use ld, st directly. Use load, extload, sextload, zextload, store, |
| 505 | // and truncst (see below). |
| 506 | def ld : SDNode<"ISD::LOAD" , SDTLoad, |
| 507 | [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; |
| 508 | def st : SDNode<"ISD::STORE" , SDTStore, |
| 509 | [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; |
| 510 | def ist : SDNode<"ISD::STORE" , SDTIStore, |
| 511 | [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; |
| 512 | |
| 513 | def vector_shuffle : SDNode<"ISD::VECTOR_SHUFFLE", SDTVecShuffle, []>; |
| 514 | def build_vector : SDNode<"ISD::BUILD_VECTOR", SDTypeProfile<1, -1, []>, []>; |
| 515 | def scalar_to_vector : SDNode<"ISD::SCALAR_TO_VECTOR", SDTypeProfile<1, 1, []>, |
| 516 | []>; |
| 517 | |
| 518 | // vector_extract/vector_insert are deprecated. extractelt/insertelt |
| 519 | // are preferred. |
| 520 | def vector_extract : SDNode<"ISD::EXTRACT_VECTOR_ELT", |
| 521 | SDTypeProfile<1, 2, [SDTCisPtrTy<2>]>, []>; |
| 522 | def vector_insert : SDNode<"ISD::INSERT_VECTOR_ELT", |
| 523 | SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisPtrTy<3>]>, []>; |
| 524 | def concat_vectors : SDNode<"ISD::CONCAT_VECTORS", |
| 525 | SDTypeProfile<1, 2, [SDTCisSubVecOfVec<1, 0>, SDTCisSameAs<1, 2>]>,[]>; |
| 526 | |
| 527 | // This operator does not do subvector type checking. The ARM |
| 528 | // backend, at least, needs it. |
| 529 | def vector_extract_subvec : SDNode<"ISD::EXTRACT_SUBVECTOR", |
| 530 | SDTypeProfile<1, 2, [SDTCisInt<2>, SDTCisVec<1>, SDTCisVec<0>]>, |
| 531 | []>; |
| 532 | |
| 533 | // This operator does subvector type checking. |
| 534 | def extract_subvector : SDNode<"ISD::EXTRACT_SUBVECTOR", SDTSubVecExtract, []>; |
| 535 | def insert_subvector : SDNode<"ISD::INSERT_SUBVECTOR", SDTSubVecInsert, []>; |
| 536 | |
| 537 | // Nodes for intrinsics, you should use the intrinsic itself and let tblgen use |
| 538 | // these internally. Don't reference these directly. |
| 539 | def intrinsic_void : SDNode<"ISD::INTRINSIC_VOID", |
| 540 | SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>, |
| 541 | [SDNPHasChain]>; |
| 542 | def intrinsic_w_chain : SDNode<"ISD::INTRINSIC_W_CHAIN", |
| 543 | SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>, |
| 544 | [SDNPHasChain]>; |
| 545 | def intrinsic_wo_chain : SDNode<"ISD::INTRINSIC_WO_CHAIN", |
| 546 | SDTypeProfile<1, -1, [SDTCisPtrTy<1>]>, []>; |
| 547 | |
| 548 | def SDT_assertext : SDTypeProfile<1, 1, |
| 549 | [SDTCisInt<0>, SDTCisInt<1>, SDTCisSameAs<1, 0>]>; |
| 550 | def assertsext : SDNode<"ISD::AssertSext", SDT_assertext>; |
| 551 | def assertzext : SDNode<"ISD::AssertZext", SDT_assertext>; |
| 552 | |
| 553 | |
| 554 | //===----------------------------------------------------------------------===// |
| 555 | // Selection DAG Condition Codes |
| 556 | |
| 557 | class CondCode; // ISD::CondCode enums |
| 558 | def SETOEQ : CondCode; def SETOGT : CondCode; |
| 559 | def SETOGE : CondCode; def SETOLT : CondCode; def SETOLE : CondCode; |
| 560 | def SETONE : CondCode; def SETO : CondCode; def SETUO : CondCode; |
| 561 | def SETUEQ : CondCode; def SETUGT : CondCode; def SETUGE : CondCode; |
| 562 | def SETULT : CondCode; def SETULE : CondCode; def SETUNE : CondCode; |
| 563 | |
| 564 | def SETEQ : CondCode; def SETGT : CondCode; def SETGE : CondCode; |
| 565 | def SETLT : CondCode; def SETLE : CondCode; def SETNE : CondCode; |
| 566 | |
| 567 | |
| 568 | //===----------------------------------------------------------------------===// |
| 569 | // Selection DAG Node Transformation Functions. |
| 570 | // |
| 571 | // This mechanism allows targets to manipulate nodes in the output DAG once a |
| 572 | // match has been formed. This is typically used to manipulate immediate |
| 573 | // values. |
| 574 | // |
| 575 | class SDNodeXForm<SDNode opc, code xformFunction> { |
| 576 | SDNode Opcode = opc; |
| 577 | code XFormFunction = xformFunction; |
| 578 | } |
| 579 | |
| 580 | def NOOP_SDNodeXForm : SDNodeXForm<imm, [{}]>; |
| 581 | |
| 582 | //===----------------------------------------------------------------------===// |
| 583 | // PatPred Subclasses. |
| 584 | // |
| 585 | // These allow specifying different sorts of predicates that control whether a |
| 586 | // node is matched. |
| 587 | // |
| 588 | class PatPred; |
| 589 | |
| 590 | class CodePatPred<code predicate> : PatPred { |
| 591 | code PredicateCode = predicate; |
| 592 | } |
| 593 | |
| 594 | |
| 595 | //===----------------------------------------------------------------------===// |
| 596 | // Selection DAG Pattern Fragments. |
| 597 | // |
| 598 | // Pattern fragments are reusable chunks of dags that match specific things. |
| 599 | // They can take arguments and have C++ predicates that control whether they |
| 600 | // match. They are intended to make the patterns for common instructions more |
| 601 | // compact and readable. |
| 602 | // |
| 603 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 604 | /// PatFrags - Represents a set of pattern fragments. Each single fragment |
| 605 | /// can match something on the DAG, from a single node to multiple nested other |
| 606 | /// fragments. The whole set of fragments matches if any of the single |
| 607 | /// fragemnts match. This allows e.g. matching and "add with overflow" and |
| 608 | /// a regular "add" with the same fragment set. |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 609 | /// |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 610 | class PatFrags<dag ops, list<dag> frags, code pred = [{}], |
| 611 | SDNodeXForm xform = NOOP_SDNodeXForm> : SDPatternOperator { |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 612 | dag Operands = ops; |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 613 | list<dag> Fragments = frags; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 614 | code PredicateCode = pred; |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 615 | code GISelPredicateCode = [{}]; |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 616 | code ImmediateCode = [{}]; |
| 617 | SDNodeXForm OperandTransform = xform; |
| 618 | |
| 619 | // Define a few pre-packaged predicates. This helps GlobalISel import |
| 620 | // existing rules from SelectionDAG for many common cases. |
| 621 | // They will be tested prior to the code in pred and must not be used in |
| 622 | // ImmLeaf and its subclasses. |
| 623 | |
| 624 | // Is the desired pre-packaged predicate for a load? |
| 625 | bit IsLoad = ?; |
| 626 | // Is the desired pre-packaged predicate for a store? |
| 627 | bit IsStore = ?; |
| 628 | // Is the desired pre-packaged predicate for an atomic? |
| 629 | bit IsAtomic = ?; |
| 630 | |
| 631 | // cast<LoadSDNode>(N)->getAddressingMode() == ISD::UNINDEXED; |
| 632 | // cast<StoreSDNode>(N)->getAddressingMode() == ISD::UNINDEXED; |
| 633 | bit IsUnindexed = ?; |
| 634 | |
| 635 | // cast<LoadSDNode>(N)->getExtensionType() != ISD::NON_EXTLOAD |
| 636 | bit IsNonExtLoad = ?; |
| 637 | // cast<LoadSDNode>(N)->getExtensionType() == ISD::EXTLOAD; |
| 638 | bit IsAnyExtLoad = ?; |
| 639 | // cast<LoadSDNode>(N)->getExtensionType() == ISD::SEXTLOAD; |
| 640 | bit IsSignExtLoad = ?; |
| 641 | // cast<LoadSDNode>(N)->getExtensionType() == ISD::ZEXTLOAD; |
| 642 | bit IsZeroExtLoad = ?; |
| 643 | // !cast<StoreSDNode>(N)->isTruncatingStore(); |
| 644 | // cast<StoreSDNode>(N)->isTruncatingStore(); |
| 645 | bit IsTruncStore = ?; |
| 646 | |
| 647 | // cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::Monotonic |
| 648 | bit IsAtomicOrderingMonotonic = ?; |
| 649 | // cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::Acquire |
| 650 | bit IsAtomicOrderingAcquire = ?; |
| 651 | // cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::Release |
| 652 | bit IsAtomicOrderingRelease = ?; |
| 653 | // cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::AcquireRelease |
| 654 | bit IsAtomicOrderingAcquireRelease = ?; |
| 655 | // cast<AtomicSDNode>(N)->getOrdering() == AtomicOrdering::SequentiallyConsistent |
| 656 | bit IsAtomicOrderingSequentiallyConsistent = ?; |
| 657 | |
| 658 | // isAcquireOrStronger(cast<AtomicSDNode>(N)->getOrdering()) |
| 659 | // !isAcquireOrStronger(cast<AtomicSDNode>(N)->getOrdering()) |
| 660 | bit IsAtomicOrderingAcquireOrStronger = ?; |
| 661 | |
| 662 | // isReleaseOrStronger(cast<AtomicSDNode>(N)->getOrdering()) |
| 663 | // !isReleaseOrStronger(cast<AtomicSDNode>(N)->getOrdering()) |
| 664 | bit IsAtomicOrderingReleaseOrStronger = ?; |
| 665 | |
| 666 | // cast<LoadSDNode>(N)->getMemoryVT() == MVT::<VT>; |
| 667 | // cast<StoreSDNode>(N)->getMemoryVT() == MVT::<VT>; |
| 668 | ValueType MemoryVT = ?; |
| 669 | // cast<LoadSDNode>(N)->getMemoryVT().getScalarType() == MVT::<VT>; |
| 670 | // cast<StoreSDNode>(N)->getMemoryVT().getScalarType() == MVT::<VT>; |
| 671 | ValueType ScalarMemoryVT = ?; |
| 672 | } |
| 673 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 674 | // PatFrag - A version of PatFrags matching only a single fragment. |
| 675 | class PatFrag<dag ops, dag frag, code pred = [{}], |
| 676 | SDNodeXForm xform = NOOP_SDNodeXForm> |
| 677 | : PatFrags<ops, [frag], pred, xform>; |
| 678 | |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 679 | // OutPatFrag is a pattern fragment that is used as part of an output pattern |
| 680 | // (not an input pattern). These do not have predicates or transforms, but are |
| 681 | // used to avoid repeated subexpressions in output patterns. |
| 682 | class OutPatFrag<dag ops, dag frag> |
| 683 | : PatFrag<ops, frag, [{}], NOOP_SDNodeXForm>; |
| 684 | |
| 685 | // PatLeaf's are pattern fragments that have no operands. This is just a helper |
| 686 | // to define immediates and other common things concisely. |
| 687 | class PatLeaf<dag frag, code pred = [{}], SDNodeXForm xform = NOOP_SDNodeXForm> |
| 688 | : PatFrag<(ops), frag, pred, xform>; |
| 689 | |
| 690 | |
| 691 | // ImmLeaf is a pattern fragment with a constraint on the immediate. The |
| 692 | // constraint is a function that is run on the immediate (always with the value |
| 693 | // sign extended out to an int64_t) as Imm. For example: |
| 694 | // |
| 695 | // def immSExt8 : ImmLeaf<i16, [{ return (char)Imm == Imm; }]>; |
| 696 | // |
| 697 | // this is a more convenient form to match 'imm' nodes in than PatLeaf and also |
| 698 | // is preferred over using PatLeaf because it allows the code generator to |
| 699 | // reason more about the constraint. |
| 700 | // |
| 701 | // If FastIsel should ignore all instructions that have an operand of this type, |
| 702 | // the FastIselShouldIgnore flag can be set. This is an optimization to reduce |
| 703 | // the code size of the generated fast instruction selector. |
| 704 | class ImmLeaf<ValueType vt, code pred, SDNodeXForm xform = NOOP_SDNodeXForm, |
| 705 | SDNode ImmNode = imm> |
| 706 | : PatFrag<(ops), (vt ImmNode), [{}], xform> { |
| 707 | let ImmediateCode = pred; |
| 708 | bit FastIselShouldIgnore = 0; |
| 709 | |
| 710 | // Is the data type of the immediate an APInt? |
| 711 | bit IsAPInt = 0; |
| 712 | |
| 713 | // Is the data type of the immediate an APFloat? |
| 714 | bit IsAPFloat = 0; |
| 715 | } |
| 716 | |
| 717 | // An ImmLeaf except that Imm is an APInt. This is useful when you need to |
| 718 | // zero-extend the immediate instead of sign-extend it. |
| 719 | // |
| 720 | // Note that FastISel does not currently understand IntImmLeaf and will not |
| 721 | // generate code for rules that make use of it. As such, it does not make sense |
| 722 | // to replace ImmLeaf with IntImmLeaf. However, replacing PatLeaf with an |
| 723 | // IntImmLeaf will allow GlobalISel to import the rule. |
| 724 | class IntImmLeaf<ValueType vt, code pred, SDNodeXForm xform = NOOP_SDNodeXForm> |
| 725 | : ImmLeaf<vt, pred, xform> { |
| 726 | let IsAPInt = 1; |
| 727 | let FastIselShouldIgnore = 1; |
| 728 | } |
| 729 | |
| 730 | // An ImmLeaf except that Imm is an APFloat. |
| 731 | // |
| 732 | // Note that FastISel does not currently understand FPImmLeaf and will not |
| 733 | // generate code for rules that make use of it. |
| 734 | class FPImmLeaf<ValueType vt, code pred, SDNodeXForm xform = NOOP_SDNodeXForm> |
| 735 | : ImmLeaf<vt, pred, xform, fpimm> { |
| 736 | let IsAPFloat = 1; |
| 737 | let FastIselShouldIgnore = 1; |
| 738 | } |
| 739 | |
| 740 | // Leaf fragments. |
| 741 | |
| 742 | def vtInt : PatLeaf<(vt), [{ return N->getVT().isInteger(); }]>; |
| 743 | def vtFP : PatLeaf<(vt), [{ return N->getVT().isFloatingPoint(); }]>; |
| 744 | |
| 745 | def immAllOnesV: PatLeaf<(build_vector), [{ |
| 746 | return ISD::isBuildVectorAllOnes(N); |
| 747 | }]>; |
| 748 | def immAllZerosV: PatLeaf<(build_vector), [{ |
| 749 | return ISD::isBuildVectorAllZeros(N); |
| 750 | }]>; |
| 751 | |
| 752 | |
| 753 | |
| 754 | // Other helper fragments. |
| 755 | def not : PatFrag<(ops node:$in), (xor node:$in, -1)>; |
| 756 | def vnot : PatFrag<(ops node:$in), (xor node:$in, immAllOnesV)>; |
| 757 | def ineg : PatFrag<(ops node:$in), (sub 0, node:$in)>; |
| 758 | |
| 759 | // null_frag - The null pattern operator is used in multiclass instantiations |
| 760 | // which accept an SDPatternOperator for use in matching patterns for internal |
| 761 | // definitions. When expanding a pattern, if the null fragment is referenced |
| 762 | // in the expansion, the pattern is discarded and it is as-if '[]' had been |
| 763 | // specified. This allows multiclasses to have the isel patterns be optional. |
| 764 | def null_frag : SDPatternOperator; |
| 765 | |
| 766 | // load fragments. |
| 767 | def unindexedload : PatFrag<(ops node:$ptr), (ld node:$ptr)> { |
| 768 | let IsLoad = 1; |
| 769 | let IsUnindexed = 1; |
| 770 | } |
| 771 | def load : PatFrag<(ops node:$ptr), (unindexedload node:$ptr)> { |
| 772 | let IsLoad = 1; |
| 773 | let IsNonExtLoad = 1; |
| 774 | } |
| 775 | |
| 776 | // extending load fragments. |
| 777 | def extload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr)> { |
| 778 | let IsLoad = 1; |
| 779 | let IsAnyExtLoad = 1; |
| 780 | } |
| 781 | def sextload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr)> { |
| 782 | let IsLoad = 1; |
| 783 | let IsSignExtLoad = 1; |
| 784 | } |
| 785 | def zextload : PatFrag<(ops node:$ptr), (unindexedload node:$ptr)> { |
| 786 | let IsLoad = 1; |
| 787 | let IsZeroExtLoad = 1; |
| 788 | } |
| 789 | |
| 790 | def extloadi1 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { |
| 791 | let IsLoad = 1; |
| 792 | let MemoryVT = i1; |
| 793 | } |
| 794 | def extloadi8 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { |
| 795 | let IsLoad = 1; |
| 796 | let MemoryVT = i8; |
| 797 | } |
| 798 | def extloadi16 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { |
| 799 | let IsLoad = 1; |
| 800 | let MemoryVT = i16; |
| 801 | } |
| 802 | def extloadi32 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { |
| 803 | let IsLoad = 1; |
| 804 | let MemoryVT = i32; |
| 805 | } |
| 806 | def extloadf32 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { |
| 807 | let IsLoad = 1; |
| 808 | let MemoryVT = f32; |
| 809 | } |
| 810 | def extloadf64 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { |
| 811 | let IsLoad = 1; |
| 812 | let MemoryVT = f64; |
| 813 | } |
| 814 | |
| 815 | def sextloadi1 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { |
| 816 | let IsLoad = 1; |
| 817 | let MemoryVT = i1; |
| 818 | } |
| 819 | def sextloadi8 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { |
| 820 | let IsLoad = 1; |
| 821 | let MemoryVT = i8; |
| 822 | } |
| 823 | def sextloadi16 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { |
| 824 | let IsLoad = 1; |
| 825 | let MemoryVT = i16; |
| 826 | } |
| 827 | def sextloadi32 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { |
| 828 | let IsLoad = 1; |
| 829 | let MemoryVT = i32; |
| 830 | } |
| 831 | |
| 832 | def zextloadi1 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { |
| 833 | let IsLoad = 1; |
| 834 | let MemoryVT = i1; |
| 835 | } |
| 836 | def zextloadi8 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { |
| 837 | let IsLoad = 1; |
| 838 | let MemoryVT = i8; |
| 839 | } |
| 840 | def zextloadi16 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { |
| 841 | let IsLoad = 1; |
| 842 | let MemoryVT = i16; |
| 843 | } |
| 844 | def zextloadi32 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { |
| 845 | let IsLoad = 1; |
| 846 | let MemoryVT = i32; |
| 847 | } |
| 848 | |
| 849 | def extloadvi1 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { |
| 850 | let IsLoad = 1; |
| 851 | let ScalarMemoryVT = i1; |
| 852 | } |
| 853 | def extloadvi8 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { |
| 854 | let IsLoad = 1; |
| 855 | let ScalarMemoryVT = i8; |
| 856 | } |
| 857 | def extloadvi16 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { |
| 858 | let IsLoad = 1; |
| 859 | let ScalarMemoryVT = i16; |
| 860 | } |
| 861 | def extloadvi32 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { |
| 862 | let IsLoad = 1; |
| 863 | let ScalarMemoryVT = i32; |
| 864 | } |
| 865 | def extloadvf32 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { |
| 866 | let IsLoad = 1; |
| 867 | let ScalarMemoryVT = f32; |
| 868 | } |
| 869 | def extloadvf64 : PatFrag<(ops node:$ptr), (extload node:$ptr)> { |
| 870 | let IsLoad = 1; |
| 871 | let ScalarMemoryVT = f64; |
| 872 | } |
| 873 | |
| 874 | def sextloadvi1 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { |
| 875 | let IsLoad = 1; |
| 876 | let ScalarMemoryVT = i1; |
| 877 | } |
| 878 | def sextloadvi8 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { |
| 879 | let IsLoad = 1; |
| 880 | let ScalarMemoryVT = i8; |
| 881 | } |
| 882 | def sextloadvi16 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { |
| 883 | let IsLoad = 1; |
| 884 | let ScalarMemoryVT = i16; |
| 885 | } |
| 886 | def sextloadvi32 : PatFrag<(ops node:$ptr), (sextload node:$ptr)> { |
| 887 | let IsLoad = 1; |
| 888 | let ScalarMemoryVT = i32; |
| 889 | } |
| 890 | |
| 891 | def zextloadvi1 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { |
| 892 | let IsLoad = 1; |
| 893 | let ScalarMemoryVT = i1; |
| 894 | } |
| 895 | def zextloadvi8 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { |
| 896 | let IsLoad = 1; |
| 897 | let ScalarMemoryVT = i8; |
| 898 | } |
| 899 | def zextloadvi16 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { |
| 900 | let IsLoad = 1; |
| 901 | let ScalarMemoryVT = i16; |
| 902 | } |
| 903 | def zextloadvi32 : PatFrag<(ops node:$ptr), (zextload node:$ptr)> { |
| 904 | let IsLoad = 1; |
| 905 | let ScalarMemoryVT = i32; |
| 906 | } |
| 907 | |
| 908 | // store fragments. |
| 909 | def unindexedstore : PatFrag<(ops node:$val, node:$ptr), |
| 910 | (st node:$val, node:$ptr)> { |
| 911 | let IsStore = 1; |
| 912 | let IsUnindexed = 1; |
| 913 | } |
| 914 | def store : PatFrag<(ops node:$val, node:$ptr), |
| 915 | (unindexedstore node:$val, node:$ptr)> { |
| 916 | let IsStore = 1; |
| 917 | let IsTruncStore = 0; |
| 918 | } |
| 919 | |
| 920 | // truncstore fragments. |
| 921 | def truncstore : PatFrag<(ops node:$val, node:$ptr), |
| 922 | (unindexedstore node:$val, node:$ptr)> { |
| 923 | let IsStore = 1; |
| 924 | let IsTruncStore = 1; |
| 925 | } |
| 926 | def truncstorei8 : PatFrag<(ops node:$val, node:$ptr), |
| 927 | (truncstore node:$val, node:$ptr)> { |
| 928 | let IsStore = 1; |
| 929 | let MemoryVT = i8; |
| 930 | } |
| 931 | def truncstorei16 : PatFrag<(ops node:$val, node:$ptr), |
| 932 | (truncstore node:$val, node:$ptr)> { |
| 933 | let IsStore = 1; |
| 934 | let MemoryVT = i16; |
| 935 | } |
| 936 | def truncstorei32 : PatFrag<(ops node:$val, node:$ptr), |
| 937 | (truncstore node:$val, node:$ptr)> { |
| 938 | let IsStore = 1; |
| 939 | let MemoryVT = i32; |
| 940 | } |
| 941 | def truncstoref32 : PatFrag<(ops node:$val, node:$ptr), |
| 942 | (truncstore node:$val, node:$ptr)> { |
| 943 | let IsStore = 1; |
| 944 | let MemoryVT = f32; |
| 945 | } |
| 946 | def truncstoref64 : PatFrag<(ops node:$val, node:$ptr), |
| 947 | (truncstore node:$val, node:$ptr)> { |
| 948 | let IsStore = 1; |
| 949 | let MemoryVT = f64; |
| 950 | } |
| 951 | |
| 952 | def truncstorevi8 : PatFrag<(ops node:$val, node:$ptr), |
| 953 | (truncstore node:$val, node:$ptr)> { |
| 954 | let IsStore = 1; |
| 955 | let ScalarMemoryVT = i8; |
| 956 | } |
| 957 | |
| 958 | def truncstorevi16 : PatFrag<(ops node:$val, node:$ptr), |
| 959 | (truncstore node:$val, node:$ptr)> { |
| 960 | let IsStore = 1; |
| 961 | let ScalarMemoryVT = i16; |
| 962 | } |
| 963 | |
| 964 | def truncstorevi32 : PatFrag<(ops node:$val, node:$ptr), |
| 965 | (truncstore node:$val, node:$ptr)> { |
| 966 | let IsStore = 1; |
| 967 | let ScalarMemoryVT = i32; |
| 968 | } |
| 969 | |
| 970 | // indexed store fragments. |
| 971 | def istore : PatFrag<(ops node:$val, node:$base, node:$offset), |
| 972 | (ist node:$val, node:$base, node:$offset)> { |
| 973 | let IsStore = 1; |
| 974 | let IsTruncStore = 0; |
| 975 | } |
| 976 | |
| 977 | def pre_store : PatFrag<(ops node:$val, node:$base, node:$offset), |
| 978 | (istore node:$val, node:$base, node:$offset), [{ |
| 979 | ISD::MemIndexedMode AM = cast<StoreSDNode>(N)->getAddressingMode(); |
| 980 | return AM == ISD::PRE_INC || AM == ISD::PRE_DEC; |
| 981 | }]>; |
| 982 | |
| 983 | def itruncstore : PatFrag<(ops node:$val, node:$base, node:$offset), |
| 984 | (ist node:$val, node:$base, node:$offset)> { |
| 985 | let IsStore = 1; |
| 986 | let IsTruncStore = 1; |
| 987 | } |
| 988 | def pre_truncst : PatFrag<(ops node:$val, node:$base, node:$offset), |
| 989 | (itruncstore node:$val, node:$base, node:$offset), [{ |
| 990 | ISD::MemIndexedMode AM = cast<StoreSDNode>(N)->getAddressingMode(); |
| 991 | return AM == ISD::PRE_INC || AM == ISD::PRE_DEC; |
| 992 | }]>; |
| 993 | def pre_truncsti1 : PatFrag<(ops node:$val, node:$base, node:$offset), |
| 994 | (pre_truncst node:$val, node:$base, node:$offset)> { |
| 995 | let IsStore = 1; |
| 996 | let MemoryVT = i1; |
| 997 | } |
| 998 | def pre_truncsti8 : PatFrag<(ops node:$val, node:$base, node:$offset), |
| 999 | (pre_truncst node:$val, node:$base, node:$offset)> { |
| 1000 | let IsStore = 1; |
| 1001 | let MemoryVT = i8; |
| 1002 | } |
| 1003 | def pre_truncsti16 : PatFrag<(ops node:$val, node:$base, node:$offset), |
| 1004 | (pre_truncst node:$val, node:$base, node:$offset)> { |
| 1005 | let IsStore = 1; |
| 1006 | let MemoryVT = i16; |
| 1007 | } |
| 1008 | def pre_truncsti32 : PatFrag<(ops node:$val, node:$base, node:$offset), |
| 1009 | (pre_truncst node:$val, node:$base, node:$offset)> { |
| 1010 | let IsStore = 1; |
| 1011 | let MemoryVT = i32; |
| 1012 | } |
| 1013 | def pre_truncstf32 : PatFrag<(ops node:$val, node:$base, node:$offset), |
| 1014 | (pre_truncst node:$val, node:$base, node:$offset)> { |
| 1015 | let IsStore = 1; |
| 1016 | let MemoryVT = f32; |
| 1017 | } |
| 1018 | |
| 1019 | def post_store : PatFrag<(ops node:$val, node:$ptr, node:$offset), |
| 1020 | (istore node:$val, node:$ptr, node:$offset), [{ |
| 1021 | ISD::MemIndexedMode AM = cast<StoreSDNode>(N)->getAddressingMode(); |
| 1022 | return AM == ISD::POST_INC || AM == ISD::POST_DEC; |
| 1023 | }]>; |
| 1024 | |
| 1025 | def post_truncst : PatFrag<(ops node:$val, node:$base, node:$offset), |
| 1026 | (itruncstore node:$val, node:$base, node:$offset), [{ |
| 1027 | ISD::MemIndexedMode AM = cast<StoreSDNode>(N)->getAddressingMode(); |
| 1028 | return AM == ISD::POST_INC || AM == ISD::POST_DEC; |
| 1029 | }]>; |
| 1030 | def post_truncsti1 : PatFrag<(ops node:$val, node:$base, node:$offset), |
| 1031 | (post_truncst node:$val, node:$base, node:$offset)> { |
| 1032 | let IsStore = 1; |
| 1033 | let MemoryVT = i1; |
| 1034 | } |
| 1035 | def post_truncsti8 : PatFrag<(ops node:$val, node:$base, node:$offset), |
| 1036 | (post_truncst node:$val, node:$base, node:$offset)> { |
| 1037 | let IsStore = 1; |
| 1038 | let MemoryVT = i8; |
| 1039 | } |
| 1040 | def post_truncsti16 : PatFrag<(ops node:$val, node:$base, node:$offset), |
| 1041 | (post_truncst node:$val, node:$base, node:$offset)> { |
| 1042 | let IsStore = 1; |
| 1043 | let MemoryVT = i16; |
| 1044 | } |
| 1045 | def post_truncsti32 : PatFrag<(ops node:$val, node:$base, node:$offset), |
| 1046 | (post_truncst node:$val, node:$base, node:$offset)> { |
| 1047 | let IsStore = 1; |
| 1048 | let MemoryVT = i32; |
| 1049 | } |
| 1050 | def post_truncstf32 : PatFrag<(ops node:$val, node:$base, node:$offset), |
| 1051 | (post_truncst node:$val, node:$base, node:$offset)> { |
| 1052 | let IsStore = 1; |
| 1053 | let MemoryVT = f32; |
| 1054 | } |
| 1055 | |
Andrew Scull | cdfcccc | 2018-10-05 20:58:37 +0100 | [diff] [blame] | 1056 | def nonvolatile_load : PatFrag<(ops node:$ptr), |
| 1057 | (load node:$ptr), [{ |
| 1058 | return !cast<LoadSDNode>(N)->isVolatile(); |
| 1059 | }]>; |
| 1060 | def nonvolatile_store : PatFrag<(ops node:$val, node:$ptr), |
| 1061 | (store node:$val, node:$ptr), [{ |
| 1062 | return !cast<StoreSDNode>(N)->isVolatile(); |
| 1063 | }]>; |
| 1064 | |
Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame] | 1065 | // nontemporal store fragments. |
| 1066 | def nontemporalstore : PatFrag<(ops node:$val, node:$ptr), |
| 1067 | (store node:$val, node:$ptr), [{ |
| 1068 | return cast<StoreSDNode>(N)->isNonTemporal(); |
| 1069 | }]>; |
| 1070 | |
| 1071 | def alignednontemporalstore : PatFrag<(ops node:$val, node:$ptr), |
| 1072 | (nontemporalstore node:$val, node:$ptr), [{ |
| 1073 | StoreSDNode *St = cast<StoreSDNode>(N); |
| 1074 | return St->getAlignment() >= St->getMemoryVT().getStoreSize(); |
| 1075 | }]>; |
| 1076 | |
| 1077 | def unalignednontemporalstore : PatFrag<(ops node:$val, node:$ptr), |
| 1078 | (nontemporalstore node:$val, node:$ptr), [{ |
| 1079 | StoreSDNode *St = cast<StoreSDNode>(N); |
| 1080 | return St->getAlignment() < St->getMemoryVT().getStoreSize(); |
| 1081 | }]>; |
| 1082 | |
| 1083 | // nontemporal load fragments. |
| 1084 | def nontemporalload : PatFrag<(ops node:$ptr), |
| 1085 | (load node:$ptr), [{ |
| 1086 | return cast<LoadSDNode>(N)->isNonTemporal(); |
| 1087 | }]>; |
| 1088 | |
| 1089 | def alignednontemporalload : PatFrag<(ops node:$ptr), |
| 1090 | (nontemporalload node:$ptr), [{ |
| 1091 | LoadSDNode *Ld = cast<LoadSDNode>(N); |
| 1092 | return Ld->getAlignment() >= Ld->getMemoryVT().getStoreSize(); |
| 1093 | }]>; |
| 1094 | |
| 1095 | // setcc convenience fragments. |
| 1096 | def setoeq : PatFrag<(ops node:$lhs, node:$rhs), |
| 1097 | (setcc node:$lhs, node:$rhs, SETOEQ)>; |
| 1098 | def setogt : PatFrag<(ops node:$lhs, node:$rhs), |
| 1099 | (setcc node:$lhs, node:$rhs, SETOGT)>; |
| 1100 | def setoge : PatFrag<(ops node:$lhs, node:$rhs), |
| 1101 | (setcc node:$lhs, node:$rhs, SETOGE)>; |
| 1102 | def setolt : PatFrag<(ops node:$lhs, node:$rhs), |
| 1103 | (setcc node:$lhs, node:$rhs, SETOLT)>; |
| 1104 | def setole : PatFrag<(ops node:$lhs, node:$rhs), |
| 1105 | (setcc node:$lhs, node:$rhs, SETOLE)>; |
| 1106 | def setone : PatFrag<(ops node:$lhs, node:$rhs), |
| 1107 | (setcc node:$lhs, node:$rhs, SETONE)>; |
| 1108 | def seto : PatFrag<(ops node:$lhs, node:$rhs), |
| 1109 | (setcc node:$lhs, node:$rhs, SETO)>; |
| 1110 | def setuo : PatFrag<(ops node:$lhs, node:$rhs), |
| 1111 | (setcc node:$lhs, node:$rhs, SETUO)>; |
| 1112 | def setueq : PatFrag<(ops node:$lhs, node:$rhs), |
| 1113 | (setcc node:$lhs, node:$rhs, SETUEQ)>; |
| 1114 | def setugt : PatFrag<(ops node:$lhs, node:$rhs), |
| 1115 | (setcc node:$lhs, node:$rhs, SETUGT)>; |
| 1116 | def setuge : PatFrag<(ops node:$lhs, node:$rhs), |
| 1117 | (setcc node:$lhs, node:$rhs, SETUGE)>; |
| 1118 | def setult : PatFrag<(ops node:$lhs, node:$rhs), |
| 1119 | (setcc node:$lhs, node:$rhs, SETULT)>; |
| 1120 | def setule : PatFrag<(ops node:$lhs, node:$rhs), |
| 1121 | (setcc node:$lhs, node:$rhs, SETULE)>; |
| 1122 | def setune : PatFrag<(ops node:$lhs, node:$rhs), |
| 1123 | (setcc node:$lhs, node:$rhs, SETUNE)>; |
| 1124 | def seteq : PatFrag<(ops node:$lhs, node:$rhs), |
| 1125 | (setcc node:$lhs, node:$rhs, SETEQ)>; |
| 1126 | def setgt : PatFrag<(ops node:$lhs, node:$rhs), |
| 1127 | (setcc node:$lhs, node:$rhs, SETGT)>; |
| 1128 | def setge : PatFrag<(ops node:$lhs, node:$rhs), |
| 1129 | (setcc node:$lhs, node:$rhs, SETGE)>; |
| 1130 | def setlt : PatFrag<(ops node:$lhs, node:$rhs), |
| 1131 | (setcc node:$lhs, node:$rhs, SETLT)>; |
| 1132 | def setle : PatFrag<(ops node:$lhs, node:$rhs), |
| 1133 | (setcc node:$lhs, node:$rhs, SETLE)>; |
| 1134 | def setne : PatFrag<(ops node:$lhs, node:$rhs), |
| 1135 | (setcc node:$lhs, node:$rhs, SETNE)>; |
| 1136 | |
| 1137 | multiclass binary_atomic_op_ord<SDNode atomic_op> { |
| 1138 | def #NAME#_monotonic : PatFrag<(ops node:$ptr, node:$val), |
| 1139 | (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> { |
| 1140 | let IsAtomic = 1; |
| 1141 | let IsAtomicOrderingMonotonic = 1; |
| 1142 | } |
| 1143 | def #NAME#_acquire : PatFrag<(ops node:$ptr, node:$val), |
| 1144 | (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> { |
| 1145 | let IsAtomic = 1; |
| 1146 | let IsAtomicOrderingAcquire = 1; |
| 1147 | } |
| 1148 | def #NAME#_release : PatFrag<(ops node:$ptr, node:$val), |
| 1149 | (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> { |
| 1150 | let IsAtomic = 1; |
| 1151 | let IsAtomicOrderingRelease = 1; |
| 1152 | } |
| 1153 | def #NAME#_acq_rel : PatFrag<(ops node:$ptr, node:$val), |
| 1154 | (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> { |
| 1155 | let IsAtomic = 1; |
| 1156 | let IsAtomicOrderingAcquireRelease = 1; |
| 1157 | } |
| 1158 | def #NAME#_seq_cst : PatFrag<(ops node:$ptr, node:$val), |
| 1159 | (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> { |
| 1160 | let IsAtomic = 1; |
| 1161 | let IsAtomicOrderingSequentiallyConsistent = 1; |
| 1162 | } |
| 1163 | } |
| 1164 | |
| 1165 | multiclass ternary_atomic_op_ord<SDNode atomic_op> { |
| 1166 | def #NAME#_monotonic : PatFrag<(ops node:$ptr, node:$cmp, node:$val), |
| 1167 | (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> { |
| 1168 | let IsAtomic = 1; |
| 1169 | let IsAtomicOrderingMonotonic = 1; |
| 1170 | } |
| 1171 | def #NAME#_acquire : PatFrag<(ops node:$ptr, node:$cmp, node:$val), |
| 1172 | (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> { |
| 1173 | let IsAtomic = 1; |
| 1174 | let IsAtomicOrderingAcquire = 1; |
| 1175 | } |
| 1176 | def #NAME#_release : PatFrag<(ops node:$ptr, node:$cmp, node:$val), |
| 1177 | (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> { |
| 1178 | let IsAtomic = 1; |
| 1179 | let IsAtomicOrderingRelease = 1; |
| 1180 | } |
| 1181 | def #NAME#_acq_rel : PatFrag<(ops node:$ptr, node:$cmp, node:$val), |
| 1182 | (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> { |
| 1183 | let IsAtomic = 1; |
| 1184 | let IsAtomicOrderingAcquireRelease = 1; |
| 1185 | } |
| 1186 | def #NAME#_seq_cst : PatFrag<(ops node:$ptr, node:$cmp, node:$val), |
| 1187 | (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> { |
| 1188 | let IsAtomic = 1; |
| 1189 | let IsAtomicOrderingSequentiallyConsistent = 1; |
| 1190 | } |
| 1191 | } |
| 1192 | |
| 1193 | multiclass binary_atomic_op<SDNode atomic_op> { |
| 1194 | def _8 : PatFrag<(ops node:$ptr, node:$val), |
| 1195 | (atomic_op node:$ptr, node:$val)> { |
| 1196 | let IsAtomic = 1; |
| 1197 | let MemoryVT = i8; |
| 1198 | } |
| 1199 | def _16 : PatFrag<(ops node:$ptr, node:$val), |
| 1200 | (atomic_op node:$ptr, node:$val)> { |
| 1201 | let IsAtomic = 1; |
| 1202 | let MemoryVT = i16; |
| 1203 | } |
| 1204 | def _32 : PatFrag<(ops node:$ptr, node:$val), |
| 1205 | (atomic_op node:$ptr, node:$val)> { |
| 1206 | let IsAtomic = 1; |
| 1207 | let MemoryVT = i32; |
| 1208 | } |
| 1209 | def _64 : PatFrag<(ops node:$ptr, node:$val), |
| 1210 | (atomic_op node:$ptr, node:$val)> { |
| 1211 | let IsAtomic = 1; |
| 1212 | let MemoryVT = i64; |
| 1213 | } |
| 1214 | |
| 1215 | defm NAME#_8 : binary_atomic_op_ord<atomic_op>; |
| 1216 | defm NAME#_16 : binary_atomic_op_ord<atomic_op>; |
| 1217 | defm NAME#_32 : binary_atomic_op_ord<atomic_op>; |
| 1218 | defm NAME#_64 : binary_atomic_op_ord<atomic_op>; |
| 1219 | } |
| 1220 | |
| 1221 | multiclass ternary_atomic_op<SDNode atomic_op> { |
| 1222 | def _8 : PatFrag<(ops node:$ptr, node:$cmp, node:$val), |
| 1223 | (atomic_op node:$ptr, node:$cmp, node:$val)> { |
| 1224 | let IsAtomic = 1; |
| 1225 | let MemoryVT = i8; |
| 1226 | } |
| 1227 | def _16 : PatFrag<(ops node:$ptr, node:$cmp, node:$val), |
| 1228 | (atomic_op node:$ptr, node:$cmp, node:$val)> { |
| 1229 | let IsAtomic = 1; |
| 1230 | let MemoryVT = i16; |
| 1231 | } |
| 1232 | def _32 : PatFrag<(ops node:$ptr, node:$cmp, node:$val), |
| 1233 | (atomic_op node:$ptr, node:$cmp, node:$val)> { |
| 1234 | let IsAtomic = 1; |
| 1235 | let MemoryVT = i32; |
| 1236 | } |
| 1237 | def _64 : PatFrag<(ops node:$ptr, node:$cmp, node:$val), |
| 1238 | (atomic_op node:$ptr, node:$cmp, node:$val)> { |
| 1239 | let IsAtomic = 1; |
| 1240 | let MemoryVT = i64; |
| 1241 | } |
| 1242 | |
| 1243 | defm NAME#_8 : ternary_atomic_op_ord<atomic_op>; |
| 1244 | defm NAME#_16 : ternary_atomic_op_ord<atomic_op>; |
| 1245 | defm NAME#_32 : ternary_atomic_op_ord<atomic_op>; |
| 1246 | defm NAME#_64 : ternary_atomic_op_ord<atomic_op>; |
| 1247 | } |
| 1248 | |
| 1249 | defm atomic_load_add : binary_atomic_op<atomic_load_add>; |
| 1250 | defm atomic_swap : binary_atomic_op<atomic_swap>; |
| 1251 | defm atomic_load_sub : binary_atomic_op<atomic_load_sub>; |
| 1252 | defm atomic_load_and : binary_atomic_op<atomic_load_and>; |
| 1253 | defm atomic_load_clr : binary_atomic_op<atomic_load_clr>; |
| 1254 | defm atomic_load_or : binary_atomic_op<atomic_load_or>; |
| 1255 | defm atomic_load_xor : binary_atomic_op<atomic_load_xor>; |
| 1256 | defm atomic_load_nand : binary_atomic_op<atomic_load_nand>; |
| 1257 | defm atomic_load_min : binary_atomic_op<atomic_load_min>; |
| 1258 | defm atomic_load_max : binary_atomic_op<atomic_load_max>; |
| 1259 | defm atomic_load_umin : binary_atomic_op<atomic_load_umin>; |
| 1260 | defm atomic_load_umax : binary_atomic_op<atomic_load_umax>; |
| 1261 | defm atomic_store : binary_atomic_op<atomic_store>; |
| 1262 | defm atomic_cmp_swap : ternary_atomic_op<atomic_cmp_swap>; |
| 1263 | |
| 1264 | def atomic_load_8 : |
| 1265 | PatFrag<(ops node:$ptr), |
| 1266 | (atomic_load node:$ptr)> { |
| 1267 | let IsAtomic = 1; |
| 1268 | let MemoryVT = i8; |
| 1269 | } |
| 1270 | def atomic_load_16 : |
| 1271 | PatFrag<(ops node:$ptr), |
| 1272 | (atomic_load node:$ptr)> { |
| 1273 | let IsAtomic = 1; |
| 1274 | let MemoryVT = i16; |
| 1275 | } |
| 1276 | def atomic_load_32 : |
| 1277 | PatFrag<(ops node:$ptr), |
| 1278 | (atomic_load node:$ptr)> { |
| 1279 | let IsAtomic = 1; |
| 1280 | let MemoryVT = i32; |
| 1281 | } |
| 1282 | def atomic_load_64 : |
| 1283 | PatFrag<(ops node:$ptr), |
| 1284 | (atomic_load node:$ptr)> { |
| 1285 | let IsAtomic = 1; |
| 1286 | let MemoryVT = i64; |
| 1287 | } |
| 1288 | |
| 1289 | //===----------------------------------------------------------------------===// |
| 1290 | // Selection DAG Pattern Support. |
| 1291 | // |
| 1292 | // Patterns are what are actually matched against by the target-flavored |
| 1293 | // instruction selection DAG. Instructions defined by the target implicitly |
| 1294 | // define patterns in most cases, but patterns can also be explicitly added when |
| 1295 | // an operation is defined by a sequence of instructions (e.g. loading a large |
| 1296 | // immediate value on RISC targets that do not support immediates as large as |
| 1297 | // their GPRs). |
| 1298 | // |
| 1299 | |
| 1300 | class Pattern<dag patternToMatch, list<dag> resultInstrs> { |
| 1301 | dag PatternToMatch = patternToMatch; |
| 1302 | list<dag> ResultInstrs = resultInstrs; |
| 1303 | list<Predicate> Predicates = []; // See class Instruction in Target.td. |
| 1304 | int AddedComplexity = 0; // See class Instruction in Target.td. |
| 1305 | } |
| 1306 | |
| 1307 | // Pat - A simple (but common) form of a pattern, which produces a simple result |
| 1308 | // not needing a full list. |
| 1309 | class Pat<dag pattern, dag result> : Pattern<pattern, [result]>; |
| 1310 | |
| 1311 | //===----------------------------------------------------------------------===// |
| 1312 | // Complex pattern definitions. |
| 1313 | // |
| 1314 | |
| 1315 | // Complex patterns, e.g. X86 addressing mode, requires pattern matching code |
| 1316 | // in C++. NumOperands is the number of operands returned by the select function; |
| 1317 | // SelectFunc is the name of the function used to pattern match the max. pattern; |
| 1318 | // RootNodes are the list of possible root nodes of the sub-dags to match. |
| 1319 | // e.g. X86 addressing mode - def addr : ComplexPattern<4, "SelectAddr", [add]>; |
| 1320 | // |
| 1321 | class ComplexPattern<ValueType ty, int numops, string fn, |
| 1322 | list<SDNode> roots = [], list<SDNodeProperty> props = [], |
| 1323 | int complexity = -1> { |
| 1324 | ValueType Ty = ty; |
| 1325 | int NumOperands = numops; |
| 1326 | string SelectFunc = fn; |
| 1327 | list<SDNode> RootNodes = roots; |
| 1328 | list<SDNodeProperty> Properties = props; |
| 1329 | int Complexity = complexity; |
| 1330 | } |