1//== LoongArchInstrInfo.td - Target Description for LoongArch -*- tablegen -*-// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file describes the LoongArch instructions in TableGen format. 10// 11//===----------------------------------------------------------------------===// 12 13//===----------------------------------------------------------------------===// 14// LoongArch specific DAG Nodes. 15//===----------------------------------------------------------------------===// 16 17// Target-independent type requirements, but with target-specific formats. 18def SDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>, 19 SDTCisVT<1, i32>]>; 20def SDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, 21 SDTCisVT<1, i32>]>; 22 23// Target-dependent type requirements. 24def SDT_LoongArchCall : SDTypeProfile<0, -1, [SDTCisVT<0, GRLenVT>]>; 25def SDT_LoongArchIntBinOpW : SDTypeProfile<1, 2, [ 26 SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64> 27]>; 28 29def SDT_LoongArchBStrIns: SDTypeProfile<1, 4, [ 30 SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisInt<3>, 31 SDTCisSameAs<3, 4> 32]>; 33 34def SDT_LoongArchBStrPick: SDTypeProfile<1, 3, [ 35 SDTCisInt<0>, SDTCisSameAs<0, 1>, SDTCisInt<2>, SDTCisSameAs<2, 3> 36]>; 37 38// "VI" means no output and an integer input. 39def SDT_LoongArchVI : SDTypeProfile<0, 1, [SDTCisVT<0, GRLenVT>]>; 40 41def SDT_LoongArchCsrrd : SDTypeProfile<1, 1, [SDTCisInt<0>, 42 SDTCisVT<1, GRLenVT>]>; 43def SDT_LoongArchCsrwr : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisSameAs<0, 1>, 44 SDTCisVT<2, GRLenVT>]>; 45def SDT_LoongArchCsrxchg : SDTypeProfile<1, 3, [SDTCisInt<0>, 46 SDTCisSameAs<0, 1>, 47 SDTCisSameAs<0, 2>, 48 SDTCisVT<3, GRLenVT>]>; 49def SDT_LoongArchIocsrwr : SDTypeProfile<0, 2, [SDTCisInt<0>, 50 SDTCisSameAs<0, 1>]>; 51def SDT_LoongArchMovgr2fcsr : SDTypeProfile<0, 2, [SDTCisVT<0, GRLenVT>, 52 SDTCisSameAs<0, 1>]>; 53def SDT_LoongArchMovfcsr2gr : SDTypeProfile<1, 1, [SDTCisVT<0, GRLenVT>, 54 SDTCisSameAs<0, 1>]>; 55 56// TODO: Add LoongArch specific DAG Nodes 57// Target-independent nodes, but with target-specific formats. 58def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart, 59 [SDNPHasChain, SDNPOutGlue]>; 60def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd, 61 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; 62 63// Target-dependent nodes. 64def loongarch_call : SDNode<"LoongArchISD::CALL", SDT_LoongArchCall, 65 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 66 SDNPVariadic]>; 67def loongarch_ret : SDNode<"LoongArchISD::RET", SDTNone, 68 [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; 69def loongarch_tail : SDNode<"LoongArchISD::TAIL", SDT_LoongArchCall, 70 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 71 SDNPVariadic]>; 72def loongarch_call_medium : SDNode<"LoongArchISD::CALL_MEDIUM", SDT_LoongArchCall, 73 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 74 SDNPVariadic]>; 75def loongarch_tail_medium : SDNode<"LoongArchISD::TAIL_MEDIUM", SDT_LoongArchCall, 76 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 77 SDNPVariadic]>; 78def loongarch_call_large : SDNode<"LoongArchISD::CALL_LARGE", SDT_LoongArchCall, 79 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 80 SDNPVariadic]>; 81def loongarch_tail_large : SDNode<"LoongArchISD::TAIL_LARGE", SDT_LoongArchCall, 82 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 83 SDNPVariadic]>; 84def loongarch_sll_w : SDNode<"LoongArchISD::SLL_W", SDT_LoongArchIntBinOpW>; 85def loongarch_sra_w : SDNode<"LoongArchISD::SRA_W", SDT_LoongArchIntBinOpW>; 86def loongarch_srl_w : SDNode<"LoongArchISD::SRL_W", SDT_LoongArchIntBinOpW>; 87def loongarch_rotr_w : SDNode<"LoongArchISD::ROTR_W", SDT_LoongArchIntBinOpW>; 88def loongarch_rotl_w : SDNode<"LoongArchISD::ROTL_W", SDT_LoongArchIntBinOpW>; 89def loongarch_crc_w_b_w 90 : SDNode<"LoongArchISD::CRC_W_B_W", SDT_LoongArchIntBinOpW, [SDNPHasChain]>; 91def loongarch_crc_w_h_w 92 : SDNode<"LoongArchISD::CRC_W_H_W", SDT_LoongArchIntBinOpW, [SDNPHasChain]>; 93def loongarch_crc_w_w_w 94 : SDNode<"LoongArchISD::CRC_W_W_W", SDT_LoongArchIntBinOpW, [SDNPHasChain]>; 95def loongarch_crc_w_d_w 96 : SDNode<"LoongArchISD::CRC_W_D_W", SDT_LoongArchIntBinOpW, [SDNPHasChain]>; 97def loongarch_crcc_w_b_w : SDNode<"LoongArchISD::CRCC_W_B_W", 98 SDT_LoongArchIntBinOpW, [SDNPHasChain]>; 99def loongarch_crcc_w_h_w : SDNode<"LoongArchISD::CRCC_W_H_W", 100 SDT_LoongArchIntBinOpW, [SDNPHasChain]>; 101def loongarch_crcc_w_w_w : SDNode<"LoongArchISD::CRCC_W_W_W", 102 SDT_LoongArchIntBinOpW, [SDNPHasChain]>; 103def loongarch_crcc_w_d_w : SDNode<"LoongArchISD::CRCC_W_D_W", 104 SDT_LoongArchIntBinOpW, [SDNPHasChain]>; 105def loongarch_bstrins 106 : SDNode<"LoongArchISD::BSTRINS", SDT_LoongArchBStrIns>; 107def loongarch_bstrpick 108 : SDNode<"LoongArchISD::BSTRPICK", SDT_LoongArchBStrPick>; 109def loongarch_revb_2h : SDNode<"LoongArchISD::REVB_2H", SDTUnaryOp>; 110def loongarch_revb_2w : SDNode<"LoongArchISD::REVB_2W", SDTUnaryOp>; 111def loongarch_bitrev_4b : SDNode<"LoongArchISD::BITREV_4B", SDTUnaryOp>; 112def loongarch_bitrev_w : SDNode<"LoongArchISD::BITREV_W", SDTUnaryOp>; 113def loongarch_clzw : SDNode<"LoongArchISD::CLZ_W", SDTIntBitCountUnaryOp>; 114def loongarch_ctzw : SDNode<"LoongArchISD::CTZ_W", SDTIntBitCountUnaryOp>; 115def loongarch_dbar : SDNode<"LoongArchISD::DBAR", SDT_LoongArchVI, 116 [SDNPHasChain, SDNPSideEffect]>; 117def loongarch_ibar : SDNode<"LoongArchISD::IBAR", SDT_LoongArchVI, 118 [SDNPHasChain, SDNPSideEffect]>; 119def loongarch_break : SDNode<"LoongArchISD::BREAK", SDT_LoongArchVI, 120 [SDNPHasChain, SDNPSideEffect]>; 121def loongarch_movfcsr2gr : SDNode<"LoongArchISD::MOVFCSR2GR", 122 SDT_LoongArchMovfcsr2gr, [SDNPHasChain]>; 123def loongarch_movgr2fcsr : SDNode<"LoongArchISD::MOVGR2FCSR", 124 SDT_LoongArchMovgr2fcsr, 125 [SDNPHasChain, SDNPSideEffect]>; 126def loongarch_syscall : SDNode<"LoongArchISD::SYSCALL", SDT_LoongArchVI, 127 [SDNPHasChain, SDNPSideEffect]>; 128def loongarch_csrrd : SDNode<"LoongArchISD::CSRRD", SDT_LoongArchCsrrd, 129 [SDNPHasChain, SDNPSideEffect]>; 130def loongarch_csrwr : SDNode<"LoongArchISD::CSRWR", SDT_LoongArchCsrwr, 131 [SDNPHasChain, SDNPSideEffect]>; 132def loongarch_csrxchg : SDNode<"LoongArchISD::CSRXCHG", 133 SDT_LoongArchCsrxchg, 134 [SDNPHasChain, SDNPSideEffect]>; 135def loongarch_iocsrrd_b : SDNode<"LoongArchISD::IOCSRRD_B", SDTUnaryOp, 136 [SDNPHasChain, SDNPSideEffect]>; 137def loongarch_iocsrrd_h : SDNode<"LoongArchISD::IOCSRRD_H", SDTUnaryOp, 138 [SDNPHasChain, SDNPSideEffect]>; 139def loongarch_iocsrrd_w : SDNode<"LoongArchISD::IOCSRRD_W", SDTUnaryOp, 140 [SDNPHasChain, SDNPSideEffect]>; 141def loongarch_iocsrrd_d : SDNode<"LoongArchISD::IOCSRRD_D", SDTUnaryOp, 142 [SDNPHasChain, SDNPSideEffect]>; 143def loongarch_iocsrwr_b : SDNode<"LoongArchISD::IOCSRWR_B", 144 SDT_LoongArchIocsrwr, 145 [SDNPHasChain, SDNPSideEffect]>; 146def loongarch_iocsrwr_h : SDNode<"LoongArchISD::IOCSRWR_H", 147 SDT_LoongArchIocsrwr, 148 [SDNPHasChain, SDNPSideEffect]>; 149def loongarch_iocsrwr_w : SDNode<"LoongArchISD::IOCSRWR_W", 150 SDT_LoongArchIocsrwr, 151 [SDNPHasChain, SDNPSideEffect]>; 152def loongarch_iocsrwr_d : SDNode<"LoongArchISD::IOCSRWR_D", 153 SDT_LoongArchIocsrwr, 154 [SDNPHasChain, SDNPSideEffect]>; 155def loongarch_cpucfg : SDNode<"LoongArchISD::CPUCFG", SDTUnaryOp, 156 [SDNPHasChain]>; 157 158def to_fclass_mask: SDNodeXForm<timm, [{ 159 uint64_t Check = N->getZExtValue(); 160 unsigned Mask = 0; 161 if (Check & fcSNan) 162 Mask |= LoongArch::FClassMaskSignalingNaN; 163 if (Check & fcQNan) 164 Mask |= LoongArch::FClassMaskQuietNaN; 165 if (Check & fcPosInf) 166 Mask |= LoongArch::FClassMaskPositiveInfinity; 167 if (Check & fcNegInf) 168 Mask |= LoongArch::FClassMaskNegativeInfinity; 169 if (Check & fcPosNormal) 170 Mask |= LoongArch::FClassMaskPositiveNormal; 171 if (Check & fcNegNormal) 172 Mask |= LoongArch::FClassMaskNegativeNormal; 173 if (Check & fcPosSubnormal) 174 Mask |= LoongArch::FClassMaskPositiveSubnormal; 175 if (Check & fcNegSubnormal) 176 Mask |= LoongArch::FClassMaskNegativeSubnormal; 177 if (Check & fcPosZero) 178 Mask |= LoongArch::FClassMaskPositiveZero; 179 if (Check & fcNegZero) 180 Mask |= LoongArch::FClassMaskNegativeZero; 181 return CurDAG->getTargetConstant(Mask, SDLoc(N), Subtarget->getGRLenVT()); 182}]>; 183 184//===----------------------------------------------------------------------===// 185// Operand and SDNode transformation definitions. 186//===----------------------------------------------------------------------===// 187 188class ImmAsmOperand<string prefix, int width, string suffix> 189 : AsmOperandClass { 190 let Name = prefix # "Imm" # width # suffix; 191 let DiagnosticType = !strconcat("Invalid", Name); 192 let RenderMethod = "addImmOperands"; 193} 194 195class SImmAsmOperand<int width, string suffix = ""> 196 : ImmAsmOperand<"S", width, suffix> { 197} 198 199class UImmAsmOperand<int width, string suffix = ""> 200 : ImmAsmOperand<"U", width, suffix> { 201} 202 203// A parse method for "$r*" or "$r*, 0", where the 0 is be silently ignored. 204// Only used for "AM*" instructions, in order to be compatible with GAS. 205def AtomicMemAsmOperand : AsmOperandClass { 206 let Name = "AtomicMemAsmOperand"; 207 let RenderMethod = "addRegOperands"; 208 let PredicateMethod = "isGPR"; 209 let ParserMethod = "parseAtomicMemOp"; 210} 211 212def GPRMemAtomic : RegisterOperand<GPR> { 213 let ParserMatchClass = AtomicMemAsmOperand; 214 let PrintMethod = "printAtomicMemOp"; 215} 216 217// A parameterized register class alternative to i32imm/i64imm from Target.td. 218def grlenimm : Operand<GRLenVT>; 219def imm32 : Operand<GRLenVT> { 220 let ParserMatchClass = ImmAsmOperand<"", 32, "">; 221} 222 223def uimm1 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<1>(Imm);}]>{ 224 let ParserMatchClass = UImmAsmOperand<1>; 225} 226 227def uimm2 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<2>(Imm);}]> { 228 let ParserMatchClass = UImmAsmOperand<2>; 229} 230 231def uimm2_plus1 : Operand<GRLenVT>, 232 ImmLeaf<GRLenVT, [{return isUInt<2>(Imm - 1);}]> { 233 let ParserMatchClass = UImmAsmOperand<2, "plus1">; 234 let EncoderMethod = "getImmOpValueSub1"; 235 let DecoderMethod = "decodeUImmOperand<2, 1>"; 236} 237 238def uimm3 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<3>(Imm);}]> { 239 let ParserMatchClass = UImmAsmOperand<3>; 240} 241 242def uimm4 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<4>(Imm);}]> { 243 let ParserMatchClass = UImmAsmOperand<4>; 244} 245 246def uimm5 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<5>(Imm);}]> { 247 let ParserMatchClass = UImmAsmOperand<5>; 248} 249 250def uimm6 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<6>(Imm);}]> { 251 let ParserMatchClass = UImmAsmOperand<6>; 252} 253 254def uimm7 : Operand<GRLenVT> { 255 let ParserMatchClass = UImmAsmOperand<7>; 256} 257 258def uimm8 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<8>(Imm);}]> { 259 let ParserMatchClass = UImmAsmOperand<8>; 260} 261 262class UImm12Operand : Operand<GRLenVT>, 263 ImmLeaf <GRLenVT, [{return isUInt<12>(Imm);}]> { 264 let DecoderMethod = "decodeUImmOperand<12>"; 265} 266 267def uimm12 : UImm12Operand { 268 let ParserMatchClass = UImmAsmOperand<12>; 269} 270 271def uimm12_ori : UImm12Operand { 272 let ParserMatchClass = UImmAsmOperand<12, "ori">; 273} 274 275def uimm14 : Operand<GRLenVT>, 276 ImmLeaf <GRLenVT, [{return isUInt<14>(Imm);}]> { 277 let ParserMatchClass = UImmAsmOperand<14>; 278} 279 280def uimm15 : Operand<GRLenVT>, 281 ImmLeaf <GRLenVT, [{return isUInt<15>(Imm);}]> { 282 let ParserMatchClass = UImmAsmOperand<15>; 283} 284 285def simm5 : Operand<GRLenVT> { 286 let ParserMatchClass = SImmAsmOperand<5>; 287 let DecoderMethod = "decodeSImmOperand<5>"; 288} 289 290def simm8 : Operand<GRLenVT> { 291 let ParserMatchClass = SImmAsmOperand<8>; 292 let DecoderMethod = "decodeSImmOperand<8>"; 293} 294 295foreach I = [1, 2, 3] in { 296def simm8_lsl # I : Operand<GRLenVT> { 297 let ParserMatchClass = SImmAsmOperand<8, "lsl" # I>; 298 let EncoderMethod = "getImmOpValueAsr<" # I # ">"; 299 let DecoderMethod = "decodeSImmOperand<8," # I # ">"; 300} 301} 302 303def simm9_lsl3 : Operand<GRLenVT> { 304 let ParserMatchClass = SImmAsmOperand<9, "lsl3">; 305 let EncoderMethod = "getImmOpValueAsr<3>"; 306 let DecoderMethod = "decodeSImmOperand<9, 3>"; 307} 308 309def simm10 : Operand<GRLenVT> { 310 let ParserMatchClass = SImmAsmOperand<10>; 311} 312 313def simm10_lsl2 : Operand<GRLenVT> { 314 let ParserMatchClass = SImmAsmOperand<10, "lsl2">; 315 let EncoderMethod = "getImmOpValueAsr<2>"; 316 let DecoderMethod = "decodeSImmOperand<10, 2>"; 317} 318 319def simm11_lsl1 : Operand<GRLenVT> { 320 let ParserMatchClass = SImmAsmOperand<11, "lsl1">; 321 let EncoderMethod = "getImmOpValueAsr<1>"; 322 let DecoderMethod = "decodeSImmOperand<11, 1>"; 323} 324 325class SImm12Operand : Operand<GRLenVT>, 326 ImmLeaf <GRLenVT, [{return isInt<12>(Imm);}]> { 327 let DecoderMethod = "decodeSImmOperand<12>"; 328} 329 330def simm12 : SImm12Operand { 331 let ParserMatchClass = SImmAsmOperand<12>; 332} 333 334def simm12_addlike : SImm12Operand { 335 let ParserMatchClass = SImmAsmOperand<12, "addlike">; 336} 337 338def simm12_lu52id : SImm12Operand { 339 let ParserMatchClass = SImmAsmOperand<12, "lu52id">; 340} 341 342def simm13 : Operand<GRLenVT> { 343 let ParserMatchClass = SImmAsmOperand<13>; 344 let DecoderMethod = "decodeSImmOperand<13>"; 345} 346 347def simm14_lsl2 : Operand<GRLenVT>, 348 ImmLeaf<GRLenVT, [{return isShiftedInt<14,2>(Imm);}]> { 349 let ParserMatchClass = SImmAsmOperand<14, "lsl2">; 350 let EncoderMethod = "getImmOpValueAsr<2>"; 351 let DecoderMethod = "decodeSImmOperand<14, 2>"; 352} 353 354def simm16 : Operand<GRLenVT> { 355 let ParserMatchClass = SImmAsmOperand<16>; 356 let DecoderMethod = "decodeSImmOperand<16>"; 357} 358 359def simm16_lsl2 : Operand<GRLenVT>, 360 ImmLeaf<GRLenVT, [{return isInt<16>(Imm>>2);}]> { 361 let ParserMatchClass = SImmAsmOperand<16, "lsl2">; 362 let EncoderMethod = "getImmOpValueAsr<2>"; 363 let DecoderMethod = "decodeSImmOperand<16, 2>"; 364} 365 366def simm16_lsl2_br : Operand<OtherVT> { 367 let ParserMatchClass = SImmAsmOperand<16, "lsl2">; 368 let EncoderMethod = "getImmOpValueAsr<2>"; 369 let DecoderMethod = "decodeSImmOperand<16, 2>"; 370} 371 372class SImm20Operand : Operand<GRLenVT> { 373 let DecoderMethod = "decodeSImmOperand<20>"; 374} 375 376def simm20 : SImm20Operand { 377 let ParserMatchClass = SImmAsmOperand<20>; 378} 379 380def simm20_pcalau12i : SImm20Operand { 381 let ParserMatchClass = SImmAsmOperand<20, "pcalau12i">; 382} 383 384def simm20_lu12iw : SImm20Operand { 385 let ParserMatchClass = SImmAsmOperand<20, "lu12iw">; 386} 387 388def simm20_lu32id : SImm20Operand { 389 let ParserMatchClass = SImmAsmOperand<20, "lu32id">; 390} 391 392def simm20_pcaddu18i : SImm20Operand { 393 let ParserMatchClass = SImmAsmOperand<20, "pcaddu18i">; 394} 395 396def simm21_lsl2 : Operand<OtherVT> { 397 let ParserMatchClass = SImmAsmOperand<21, "lsl2">; 398 let EncoderMethod = "getImmOpValueAsr<2>"; 399 let DecoderMethod = "decodeSImmOperand<21, 2>"; 400} 401 402def SImm26OperandB: AsmOperandClass { 403 let Name = "SImm26OperandB"; 404 let PredicateMethod = "isSImm26Operand"; 405 let RenderMethod = "addImmOperands"; 406 let DiagnosticType = "InvalidSImm26Operand"; 407 let ParserMethod = "parseImmediate"; 408} 409 410// A symbol or an imm used in B/PseudoBR. 411def simm26_b : Operand<OtherVT> { 412 let ParserMatchClass = SImm26OperandB; 413 let EncoderMethod = "getImmOpValueAsr<2>"; 414 let DecoderMethod = "decodeSImmOperand<26, 2>"; 415} 416 417def SImm26OperandBL: AsmOperandClass { 418 let Name = "SImm26OperandBL"; 419 let PredicateMethod = "isSImm26Operand"; 420 let RenderMethod = "addImmOperands"; 421 let DiagnosticType = "InvalidSImm26Operand"; 422 let ParserMethod = "parseSImm26Operand"; 423} 424 425// A symbol or an imm used in BL/PseudoCALL/PseudoTAIL. 426def simm26_symbol : Operand<GRLenVT> { 427 let ParserMatchClass = SImm26OperandBL; 428 let EncoderMethod = "getImmOpValueAsr<2>"; 429 let DecoderMethod = "decodeSImmOperand<26, 2>"; 430} 431 432// A 32-bit signed immediate with the lowest 16 bits zeroed, suitable for 433// direct use with `addu16i.d`. 434def simm16_lsl16 : Operand<GRLenVT>, 435 ImmLeaf<GRLenVT, [{return isShiftedInt<16, 16>(Imm);}]>; 436 437// A 32-bit signed immediate expressible with a pair of `addu16i.d + addi` for 438// use in additions. 439def simm32_hi16_lo12: Operand<GRLenVT>, ImmLeaf<GRLenVT, [{ 440 return isShiftedInt<16, 16>(Imm - SignExtend64<12>(Imm)); 441}]>; 442 443def BareSymbol : AsmOperandClass { 444 let Name = "BareSymbol"; 445 let RenderMethod = "addImmOperands"; 446 let DiagnosticType = "InvalidBareSymbol"; 447 let ParserMethod = "parseImmediate"; 448} 449 450// A bare symbol used in "PseudoLA_*" instructions. 451def bare_symbol : Operand<GRLenVT> { 452 let ParserMatchClass = BareSymbol; 453} 454 455// Standalone (codegen-only) immleaf patterns. 456 457// A 12-bit signed immediate plus one where the imm range will be [-2047, 2048]. 458def simm12_plus1 : ImmLeaf<GRLenVT, 459 [{return (isInt<12>(Imm) && Imm != -2048) || Imm == 2048;}]>; 460 461// Return the negation of an immediate value. 462def NegImm : SDNodeXForm<imm, [{ 463 return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N), 464 N->getValueType(0)); 465}]>; 466 467// FP immediate patterns. 468def fpimm0 : PatLeaf<(fpimm), [{return N->isExactlyValue(+0.0);}]>; 469def fpimm0neg : PatLeaf<(fpimm), [{return N->isExactlyValue(-0.0);}]>; 470def fpimm1 : PatLeaf<(fpimm), [{return N->isExactlyValue(+1.0);}]>; 471 472// Return an immediate subtracted from 32. 473def ImmSubFrom32 : SDNodeXForm<imm, [{ 474 return CurDAG->getTargetConstant(32 - N->getZExtValue(), SDLoc(N), 475 N->getValueType(0)); 476}]>; 477 478// Return the lowest 12 bits of the signed immediate. 479def LO12: SDNodeXForm<imm, [{ 480 return CurDAG->getTargetConstant(SignExtend64<12>(N->getSExtValue()), 481 SDLoc(N), N->getValueType(0)); 482}]>; 483 484// Return the higher 16 bits of the signed immediate. 485def HI16 : SDNodeXForm<imm, [{ 486 return CurDAG->getTargetConstant(N->getSExtValue() >> 16, SDLoc(N), 487 N->getValueType(0)); 488}]>; 489 490// Return the higher 16 bits of the signed immediate, adjusted for use within an 491// `addu16i.d + addi` pair. 492def HI16ForAddu16idAddiPair: SDNodeXForm<imm, [{ 493 auto Imm = N->getSExtValue(); 494 return CurDAG->getTargetConstant((Imm - SignExtend64<12>(Imm)) >> 16, 495 SDLoc(N), N->getValueType(0)); 496}]>; 497 498def BaseAddr : ComplexPattern<iPTR, 1, "SelectBaseAddr">; 499def AddrConstant : ComplexPattern<iPTR, 2, "SelectAddrConstant">; 500def NonFIBaseAddr : ComplexPattern<iPTR, 1, "selectNonFIBaseAddr">; 501 502def fma_nsz : PatFrag<(ops node:$fj, node:$fk, node:$fa), 503 (fma node:$fj, node:$fk, node:$fa), [{ 504 return N->getFlags().hasNoSignedZeros(); 505}]>; 506 507// Check if (add r, imm) can be optimized to (ADDI (ADDI r, imm0), imm1), 508// in which imm = imm0 + imm1, and both imm0 & imm1 are simm12. 509def AddiPair : PatLeaf<(imm), [{ 510 if (!N->hasOneUse()) 511 return false; 512 // The immediate operand must be in range [-4096,-2049] or [2048,4094]. 513 int64_t Imm = N->getSExtValue(); 514 return (-4096 <= Imm && Imm <= -2049) || (2048 <= Imm && Imm <= 4094); 515}]>; 516 517// Return -2048 if immediate is negative or 2047 if positive. 518def AddiPairImmLarge : SDNodeXForm<imm, [{ 519 int64_t Imm = N->getSExtValue() < 0 ? -2048 : 2047; 520 return CurDAG->getTargetConstant(Imm, SDLoc(N), 521 N->getValueType(0)); 522}]>; 523 524// Return imm - (imm < 0 ? -2048 : 2047). 525def AddiPairImmSmall : SDNodeXForm<imm, [{ 526 int64_t Imm = N->getSExtValue(); 527 int64_t Adj = Imm < 0 ? -2048 : 2047; 528 return CurDAG->getTargetConstant(Imm - Adj, SDLoc(N), 529 N->getValueType(0)); 530}]>; 531 532// Check if (mul r, imm) can be optimized to (SLLI (ALSL r, r, i0), i1), 533// in which imm = (1 + (1 << i0)) << i1. 534def AlslSlliImm : PatLeaf<(imm), [{ 535 if (!N->hasOneUse()) 536 return false; 537 uint64_t Imm = N->getZExtValue(); 538 unsigned I1 = llvm::countr_zero(Imm); 539 uint64_t Rem = Imm >> I1; 540 return Rem == 3 || Rem == 5 || Rem == 9 || Rem == 17; 541}]>; 542 543def AlslSlliImmI1 : SDNodeXForm<imm, [{ 544 uint64_t Imm = N->getZExtValue(); 545 unsigned I1 = llvm::countr_zero(Imm); 546 return CurDAG->getTargetConstant(I1, SDLoc(N), 547 N->getValueType(0)); 548}]>; 549 550def AlslSlliImmI0 : SDNodeXForm<imm, [{ 551 uint64_t Imm = N->getZExtValue(); 552 unsigned I1 = llvm::countr_zero(Imm); 553 uint64_t I0; 554 switch (Imm >> I1) { 555 case 3: I0 = 1; break; 556 case 5: I0 = 2; break; 557 case 9: I0 = 3; break; 558 default: I0 = 4; break; 559 } 560 return CurDAG->getTargetConstant(I0, SDLoc(N), 561 N->getValueType(0)); 562}]>; 563 564// Check if (and r, imm) can be optimized to (BSTRINS r, R0, msb, lsb), 565// in which imm = ~((2^^(msb-lsb+1) - 1) << lsb). 566def BstrinsImm : PatLeaf<(imm), [{ 567 if (!N->hasOneUse()) 568 return false; 569 uint64_t Imm = N->getZExtValue(); 570 // andi can be used instead if Imm <= 0xfff. 571 if (Imm <= 0xfff) 572 return false; 573 unsigned MaskIdx, MaskLen; 574 return N->getValueType(0).getSizeInBits() == 32 575 ? llvm::isShiftedMask_32(~Imm, MaskIdx, MaskLen) 576 : llvm::isShiftedMask_64(~Imm, MaskIdx, MaskLen); 577}]>; 578 579def BstrinsMsb: SDNodeXForm<imm, [{ 580 uint64_t Imm = N->getZExtValue(); 581 unsigned MaskIdx, MaskLen; 582 N->getValueType(0).getSizeInBits() == 32 583 ? llvm::isShiftedMask_32(~Imm, MaskIdx, MaskLen) 584 : llvm::isShiftedMask_64(~Imm, MaskIdx, MaskLen); 585 return CurDAG->getTargetConstant(MaskIdx + MaskLen - 1, SDLoc(N), 586 N->getValueType(0)); 587}]>; 588 589def BstrinsLsb: SDNodeXForm<imm, [{ 590 uint64_t Imm = N->getZExtValue(); 591 unsigned MaskIdx, MaskLen; 592 N->getValueType(0).getSizeInBits() == 32 593 ? llvm::isShiftedMask_32(~Imm, MaskIdx, MaskLen) 594 : llvm::isShiftedMask_64(~Imm, MaskIdx, MaskLen); 595 return CurDAG->getTargetConstant(MaskIdx, SDLoc(N), N->getValueType(0)); 596}]>; 597 598//===----------------------------------------------------------------------===// 599// Instruction Formats 600//===----------------------------------------------------------------------===// 601 602include "LoongArchInstrFormats.td" 603include "LoongArchFloatInstrFormats.td" 604include "LoongArchLSXInstrFormats.td" 605include "LoongArchLASXInstrFormats.td" 606include "LoongArchLBTInstrFormats.td" 607 608//===----------------------------------------------------------------------===// 609// Instruction Class Templates 610//===----------------------------------------------------------------------===// 611 612let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { 613class ALU_3R<bits<32> op> 614 : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk), "$rd, $rj, $rk">; 615class ALU_2R<bits<32> op> 616 : Fmt2R<op, (outs GPR:$rd), (ins GPR:$rj), "$rd, $rj">; 617 618class ALU_3RI2<bits<32> op, Operand ImmOpnd> 619 : Fmt3RI2<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk, ImmOpnd:$imm2), 620 "$rd, $rj, $rk, $imm2">; 621class ALU_3RI3<bits<32> op, Operand ImmOpnd> 622 : Fmt3RI3<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk, ImmOpnd:$imm3), 623 "$rd, $rj, $rk, $imm3">; 624class ALU_2RI5<bits<32> op, Operand ImmOpnd> 625 : Fmt2RI5<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm5), 626 "$rd, $rj, $imm5">; 627class ALU_2RI6<bits<32> op, Operand ImmOpnd> 628 : Fmt2RI6<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm6), 629 "$rd, $rj, $imm6">; 630class ALU_2RI12<bits<32> op, Operand ImmOpnd> 631 : Fmt2RI12<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm12), 632 "$rd, $rj, $imm12">; 633class ALU_2RI16<bits<32> op, Operand ImmOpnd> 634 : Fmt2RI16<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm16), 635 "$rd, $rj, $imm16">; 636class ALU_1RI20<bits<32> op, Operand ImmOpnd> 637 : Fmt1RI20<op, (outs GPR:$rd), (ins ImmOpnd:$imm20), "$rd, $imm20">; 638} // hasSideEffects = 0, mayLoad = 0, mayStore = 0 639 640let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 641class MISC_I15<bits<32> op> 642 : FmtI15<op, (outs), (ins uimm15:$imm15), "$imm15">; 643 644let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 645class RDTIME_2R<bits<32> op> 646 : Fmt2R<op, (outs GPR:$rd, GPR:$rj), (ins), "$rd, $rj">; 647 648let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { 649class BrCC_2RI16<bits<32> op> 650 : Fmt2RI16<op, (outs), (ins GPR:$rj, GPR:$rd, simm16_lsl2_br:$imm16), 651 "$rj, $rd, $imm16"> { 652 let isBranch = 1; 653 let isTerminator = 1; 654} 655class BrCCZ_1RI21<bits<32> op> 656 : Fmt1RI21<op, (outs), (ins GPR:$rj, simm21_lsl2:$imm21), 657 "$rj, $imm21"> { 658 let isBranch = 1; 659 let isTerminator = 1; 660} 661class Br_I26<bits<32> op> 662 : FmtI26<op, (outs), (ins simm26_b:$imm26), "$imm26"> { 663 let isBranch = 1; 664 let isTerminator = 1; 665 let isBarrier = 1; 666} 667} // hasSideEffects = 0, mayLoad = 0, mayStore = 0 668 669let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { 670class LOAD_3R<bits<32> op> 671 : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk), "$rd, $rj, $rk">; 672class LOAD_2RI12<bits<32> op> 673 : Fmt2RI12<op, (outs GPR:$rd), (ins GPR:$rj, simm12_addlike:$imm12), 674 "$rd, $rj, $imm12">; 675class LOAD_2RI14<bits<32> op> 676 : Fmt2RI14<op, (outs GPR:$rd), (ins GPR:$rj, simm14_lsl2:$imm14), 677 "$rd, $rj, $imm14">; 678} // hasSideEffects = 0, mayLoad = 1, mayStore = 0 679 680let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in { 681class STORE_3R<bits<32> op> 682 : Fmt3R<op, (outs), (ins GPR:$rd, GPR:$rj, GPR:$rk), 683 "$rd, $rj, $rk">; 684class STORE_2RI12<bits<32> op> 685 : Fmt2RI12<op, (outs), (ins GPR:$rd, GPR:$rj, simm12_addlike:$imm12), 686 "$rd, $rj, $imm12">; 687class STORE_2RI14<bits<32> op> 688 : Fmt2RI14<op, (outs), (ins GPR:$rd, GPR:$rj, simm14_lsl2:$imm14), 689 "$rd, $rj, $imm14">; 690} // hasSideEffects = 0, mayLoad = 0, mayStore = 1 691 692let hasSideEffects = 0, mayLoad = 1, mayStore = 1, Constraints = "@earlyclobber $rd" in 693class AM_3R<bits<32> op> 694 : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rk, GPRMemAtomic:$rj), 695 "$rd, $rk, $rj">; 696 697let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { 698class LLBase<bits<32> op> 699 : Fmt2RI14<op, (outs GPR:$rd), (ins GPR:$rj, simm14_lsl2:$imm14), 700 "$rd, $rj, $imm14">; 701class LLBase_ACQ<bits<32> op> 702 : Fmt2R<op, (outs GPR:$rd), (ins GPR:$rj), "$rd, $rj">; 703} 704 705let hasSideEffects = 0, mayLoad = 0, mayStore = 1, Constraints = "$rd = $dst" in { 706class SCBase<bits<32> op> 707 : Fmt2RI14<op, (outs GPR:$dst), (ins GPR:$rd, GPR:$rj, simm14_lsl2:$imm14), 708 "$rd, $rj, $imm14">; 709class SCBase_128<bits<32> op> 710 : Fmt3R<op, (outs GPR:$dst), (ins GPR:$rd, GPR:$rk, GPR:$rj), 711 "$rd, $rk, $rj">; 712class SCBase_REL<bits<32> op> 713 : Fmt2R<op, (outs GPR:$dst), (ins GPR:$rd, GPR:$rj), "$rd, $rj">; 714} 715 716let hasSideEffects = 1 in 717class IOCSRRD<bits<32> op> 718 : Fmt2R<op, (outs GPR:$rd), (ins GPR:$rj), "$rd, $rj">; 719 720let hasSideEffects = 1 in 721class IOCSRWR<bits<32> op> 722 : Fmt2R<op, (outs), (ins GPR:$rd, GPR:$rj), "$rd, $rj">; 723 724//===----------------------------------------------------------------------===// 725// Basic Integer Instructions 726//===----------------------------------------------------------------------===// 727 728// Arithmetic Operation Instructions 729def ADD_W : ALU_3R<0x00100000>; 730def SUB_W : ALU_3R<0x00110000>; 731def ADDI_W : ALU_2RI12<0x02800000, simm12_addlike>; 732def ALSL_W : ALU_3RI2<0x00040000, uimm2_plus1>; 733def LU12I_W : ALU_1RI20<0x14000000, simm20_lu12iw>; 734def SLT : ALU_3R<0x00120000>; 735def SLTU : ALU_3R<0x00128000>; 736def SLTI : ALU_2RI12<0x02000000, simm12>; 737def SLTUI : ALU_2RI12<0x02400000, simm12>; 738def PCADDI : ALU_1RI20<0x18000000, simm20>; 739def PCADDU12I : ALU_1RI20<0x1c000000, simm20>; 740def PCALAU12I : ALU_1RI20<0x1a000000, simm20_pcalau12i>; 741def AND : ALU_3R<0x00148000>; 742def OR : ALU_3R<0x00150000>; 743def NOR : ALU_3R<0x00140000>; 744def XOR : ALU_3R<0x00158000>; 745def ANDN : ALU_3R<0x00168000>; 746def ORN : ALU_3R<0x00160000>; 747def ANDI : ALU_2RI12<0x03400000, uimm12>; 748def ORI : ALU_2RI12<0x03800000, uimm12_ori>; 749def XORI : ALU_2RI12<0x03c00000, uimm12>; 750def MUL_W : ALU_3R<0x001c0000>; 751def MULH_W : ALU_3R<0x001c8000>; 752def MULH_WU : ALU_3R<0x001d0000>; 753let usesCustomInserter = true in { 754def DIV_W : ALU_3R<0x00200000>; 755def MOD_W : ALU_3R<0x00208000>; 756def DIV_WU : ALU_3R<0x00210000>; 757def MOD_WU : ALU_3R<0x00218000>; 758} // usesCustomInserter = true 759 760// Bit-shift Instructions 761def SLL_W : ALU_3R<0x00170000>; 762def SRL_W : ALU_3R<0x00178000>; 763def SRA_W : ALU_3R<0x00180000>; 764def ROTR_W : ALU_3R<0x001b0000>; 765 766def SLLI_W : ALU_2RI5<0x00408000, uimm5>; 767def SRLI_W : ALU_2RI5<0x00448000, uimm5>; 768def SRAI_W : ALU_2RI5<0x00488000, uimm5>; 769def ROTRI_W : ALU_2RI5<0x004c8000, uimm5>; 770 771// Bit-manipulation Instructions 772def EXT_W_B : ALU_2R<0x00005c00>; 773def EXT_W_H : ALU_2R<0x00005800>; 774def CLO_W : ALU_2R<0x00001000>; 775def CLZ_W : ALU_2R<0x00001400>; 776def CTO_W : ALU_2R<0x00001800>; 777def CTZ_W : ALU_2R<0x00001c00>; 778def BYTEPICK_W : ALU_3RI2<0x00080000, uimm2>; 779def REVB_2H : ALU_2R<0x00003000>; 780def BITREV_4B : ALU_2R<0x00004800>; 781def BITREV_W : ALU_2R<0x00005000>; 782let Constraints = "$rd = $dst" in { 783def BSTRINS_W : FmtBSTR_W<0x00600000, (outs GPR:$dst), 784 (ins GPR:$rd, GPR:$rj, uimm5:$msbw, uimm5:$lsbw), 785 "$rd, $rj, $msbw, $lsbw">; 786} 787def BSTRPICK_W : FmtBSTR_W<0x00608000, (outs GPR:$rd), 788 (ins GPR:$rj, uimm5:$msbw, uimm5:$lsbw), 789 "$rd, $rj, $msbw, $lsbw">; 790def MASKEQZ : ALU_3R<0x00130000>; 791def MASKNEZ : ALU_3R<0x00138000>; 792 793// Branch Instructions 794def BEQ : BrCC_2RI16<0x58000000>; 795def BNE : BrCC_2RI16<0x5c000000>; 796def BLT : BrCC_2RI16<0x60000000>; 797def BGE : BrCC_2RI16<0x64000000>; 798def BLTU : BrCC_2RI16<0x68000000>; 799def BGEU : BrCC_2RI16<0x6c000000>; 800def BEQZ : BrCCZ_1RI21<0x40000000>; 801def BNEZ : BrCCZ_1RI21<0x44000000>; 802def B : Br_I26<0x50000000>; 803 804let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCall = 1, Defs=[R1] in 805def BL : FmtI26<0x54000000, (outs), (ins simm26_symbol:$imm26), "$imm26">; 806let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 807def JIRL : Fmt2RI16<0x4c000000, (outs GPR:$rd), 808 (ins GPR:$rj, simm16_lsl2:$imm16), "$rd, $rj, $imm16">; 809 810// Common Memory Access Instructions 811def LD_B : LOAD_2RI12<0x28000000>; 812def LD_H : LOAD_2RI12<0x28400000>; 813def LD_W : LOAD_2RI12<0x28800000>; 814def LD_BU : LOAD_2RI12<0x2a000000>; 815def LD_HU : LOAD_2RI12<0x2a400000>; 816def ST_B : STORE_2RI12<0x29000000>; 817def ST_H : STORE_2RI12<0x29400000>; 818def ST_W : STORE_2RI12<0x29800000>; 819let hasSideEffects = 0, mayLoad = 1, mayStore = 1 in 820def PRELD : FmtPRELD<(outs), (ins uimm5:$imm5, GPR:$rj, simm12:$imm12), 821 "$imm5, $rj, $imm12">; 822 823// Atomic Memory Access Instructions 824def LL_W : LLBase<0x20000000>; 825def SC_W : SCBase<0x21000000>; 826def LLACQ_W : LLBase_ACQ<0x38578000>; 827def SCREL_W : SCBase_REL<0x38578400>; 828 829// Barrier Instructions 830def DBAR : MISC_I15<0x38720000>; 831def IBAR : MISC_I15<0x38728000>; 832 833// Other Miscellaneous Instructions 834def SYSCALL : MISC_I15<0x002b0000>; 835def BREAK : MISC_I15<0x002a0000>; 836def RDTIMEL_W : RDTIME_2R<0x00006000>; 837def RDTIMEH_W : RDTIME_2R<0x00006400>; 838def CPUCFG : ALU_2R<0x00006c00>; 839 840// Cache Maintenance Instructions 841def CACOP : FmtCACOP<(outs), (ins uimm5:$op, GPR:$rj, simm12:$imm12), 842 "$op, $rj, $imm12">; 843 844/// LA64 instructions 845 846let Predicates = [IsLA64] in { 847 848// Arithmetic Operation Instructions for 64-bits 849def ADD_D : ALU_3R<0x00108000>; 850def SUB_D : ALU_3R<0x00118000>; 851def ADDI_D : ALU_2RI12<0x02c00000, simm12_addlike>; 852def ADDU16I_D : ALU_2RI16<0x10000000, simm16>; 853def ALSL_WU : ALU_3RI2<0x00060000, uimm2_plus1>; 854def ALSL_D : ALU_3RI2<0x002c0000, uimm2_plus1>; 855let Constraints = "$rd = $dst" in { 856let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 857def LU32I_D : Fmt1RI20<0x16000000, (outs GPR:$dst), 858 (ins GPR:$rd, simm20_lu32id:$imm20), 859 "$rd, $imm20">; 860} 861def LU52I_D : ALU_2RI12<0x03000000, simm12_lu52id>; 862def PCADDU18I : ALU_1RI20<0x1e000000, simm20_pcaddu18i>; 863def MUL_D : ALU_3R<0x001d8000>; 864def MULH_D : ALU_3R<0x001e0000>; 865def MULH_DU : ALU_3R<0x001e8000>; 866def MULW_D_W : ALU_3R<0x001f0000>; 867def MULW_D_WU : ALU_3R<0x001f8000>; 868let usesCustomInserter = true in { 869def DIV_D : ALU_3R<0x00220000>; 870def MOD_D : ALU_3R<0x00228000>; 871def DIV_DU : ALU_3R<0x00230000>; 872def MOD_DU : ALU_3R<0x00238000>; 873} // usesCustomInserter = true 874 875// Bit-shift Instructions for 64-bits 876def SLL_D : ALU_3R<0x00188000>; 877def SRL_D : ALU_3R<0x00190000>; 878def SRA_D : ALU_3R<0x00198000>; 879def ROTR_D : ALU_3R<0x001b8000>; 880def SLLI_D : ALU_2RI6<0x00410000, uimm6>; 881def SRLI_D : ALU_2RI6<0x00450000, uimm6>; 882def SRAI_D : ALU_2RI6<0x00490000, uimm6>; 883def ROTRI_D : ALU_2RI6<0x004d0000, uimm6>; 884 885// Bit-manipulation Instructions for 64-bits 886def CLO_D : ALU_2R<0x00002000>; 887def CLZ_D : ALU_2R<0x00002400>; 888def CTO_D : ALU_2R<0x00002800>; 889def CTZ_D : ALU_2R<0x00002c00>; 890def BYTEPICK_D : ALU_3RI3<0x000c0000, uimm3>; 891def REVB_4H : ALU_2R<0x00003400>; 892def REVB_2W : ALU_2R<0x00003800>; 893def REVB_D : ALU_2R<0x00003c00>; 894def REVH_2W : ALU_2R<0x00004000>; 895def REVH_D : ALU_2R<0x00004400>; 896def BITREV_8B : ALU_2R<0x00004c00>; 897def BITREV_D : ALU_2R<0x00005400>; 898let Constraints = "$rd = $dst" in { 899def BSTRINS_D : FmtBSTR_D<0x00800000, (outs GPR:$dst), 900 (ins GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd), 901 "$rd, $rj, $msbd, $lsbd">; 902} 903def BSTRPICK_D : FmtBSTR_D<0x00c00000, (outs GPR:$rd), 904 (ins GPR:$rj, uimm6:$msbd, uimm6:$lsbd), 905 "$rd, $rj, $msbd, $lsbd">; 906 907// Common Memory Access Instructions for 64-bits 908def LD_WU : LOAD_2RI12<0x2a800000>; 909def LD_D : LOAD_2RI12<0x28c00000>; 910def ST_D : STORE_2RI12<0x29c00000>; 911def LDX_B : LOAD_3R<0x38000000>; 912def LDX_H : LOAD_3R<0x38040000>; 913def LDX_W : LOAD_3R<0x38080000>; 914def LDX_D : LOAD_3R<0x380c0000>; 915def LDX_BU : LOAD_3R<0x38200000>; 916def LDX_HU : LOAD_3R<0x38240000>; 917def LDX_WU : LOAD_3R<0x38280000>; 918def STX_B : STORE_3R<0x38100000>; 919def STX_H : STORE_3R<0x38140000>; 920def STX_W : STORE_3R<0x38180000>; 921def STX_D : STORE_3R<0x381c0000>; 922def LDPTR_W : LOAD_2RI14<0x24000000>; 923def LDPTR_D : LOAD_2RI14<0x26000000>; 924def STPTR_W : STORE_2RI14<0x25000000>; 925def STPTR_D : STORE_2RI14<0x27000000>; 926let hasSideEffects = 0, mayLoad = 1, mayStore = 1 in 927def PRELDX : FmtPRELDX<(outs), (ins uimm5:$imm5, GPR:$rj, GPR:$rk), 928 "$imm5, $rj, $rk">; 929 930// Bound Check Memory Access Instructions 931def LDGT_B : LOAD_3R<0x38780000>; 932def LDGT_H : LOAD_3R<0x38788000>; 933def LDGT_W : LOAD_3R<0x38790000>; 934def LDGT_D : LOAD_3R<0x38798000>; 935def LDLE_B : LOAD_3R<0x387a0000>; 936def LDLE_H : LOAD_3R<0x387a8000>; 937def LDLE_W : LOAD_3R<0x387b0000>; 938def LDLE_D : LOAD_3R<0x387b8000>; 939def STGT_B : STORE_3R<0x387c0000>; 940def STGT_H : STORE_3R<0x387c8000>; 941def STGT_W : STORE_3R<0x387d0000>; 942def STGT_D : STORE_3R<0x387d8000>; 943def STLE_B : STORE_3R<0x387e0000>; 944def STLE_H : STORE_3R<0x387e8000>; 945def STLE_W : STORE_3R<0x387f0000>; 946def STLE_D : STORE_3R<0x387f8000>; 947 948// Atomic Memory Access Instructions for 64-bits 949def AMSWAP_B : AM_3R<0x385c0000>; 950def AMSWAP_H : AM_3R<0x385c8000>; 951def AMSWAP_W : AM_3R<0x38600000>; 952def AMSWAP_D : AM_3R<0x38608000>; 953def AMADD_B : AM_3R<0x385d0000>; 954def AMADD_H : AM_3R<0x385d8000>; 955def AMADD_W : AM_3R<0x38610000>; 956def AMADD_D : AM_3R<0x38618000>; 957def AMAND_W : AM_3R<0x38620000>; 958def AMAND_D : AM_3R<0x38628000>; 959def AMOR_W : AM_3R<0x38630000>; 960def AMOR_D : AM_3R<0x38638000>; 961def AMXOR_W : AM_3R<0x38640000>; 962def AMXOR_D : AM_3R<0x38648000>; 963def AMMAX_W : AM_3R<0x38650000>; 964def AMMAX_D : AM_3R<0x38658000>; 965def AMMIN_W : AM_3R<0x38660000>; 966def AMMIN_D : AM_3R<0x38668000>; 967def AMMAX_WU : AM_3R<0x38670000>; 968def AMMAX_DU : AM_3R<0x38678000>; 969def AMMIN_WU : AM_3R<0x38680000>; 970def AMMIN_DU : AM_3R<0x38688000>; 971def AMSWAP__DB_B : AM_3R<0x385e0000>; 972def AMSWAP__DB_H : AM_3R<0x385e8000>; 973def AMSWAP__DB_W : AM_3R<0x38690000>; 974def AMSWAP__DB_D : AM_3R<0x38698000>; 975def AMADD__DB_B : AM_3R<0x385f0000>; 976def AMADD__DB_H : AM_3R<0x385f8000>; 977def AMADD__DB_W : AM_3R<0x386a0000>; 978def AMADD__DB_D : AM_3R<0x386a8000>; 979def AMAND__DB_W : AM_3R<0x386b0000>; 980def AMAND__DB_D : AM_3R<0x386b8000>; 981def AMOR__DB_W : AM_3R<0x386c0000>; 982def AMOR__DB_D : AM_3R<0x386c8000>; 983def AMXOR__DB_W : AM_3R<0x386d0000>; 984def AMXOR__DB_D : AM_3R<0x386d8000>; 985def AMMAX__DB_W : AM_3R<0x386e0000>; 986def AMMAX__DB_D : AM_3R<0x386e8000>; 987def AMMIN__DB_W : AM_3R<0x386f0000>; 988def AMMIN__DB_D : AM_3R<0x386f8000>; 989def AMMAX__DB_WU : AM_3R<0x38700000>; 990def AMMAX__DB_DU : AM_3R<0x38708000>; 991def AMMIN__DB_WU : AM_3R<0x38710000>; 992def AMMIN__DB_DU : AM_3R<0x38718000>; 993def AMCAS_B : AM_3R<0x38580000>; 994def AMCAS_H : AM_3R<0x38588000>; 995def AMCAS_W : AM_3R<0x38590000>; 996def AMCAS_D : AM_3R<0x38598000>; 997def AMCAS__DB_B : AM_3R<0x385a0000>; 998def AMCAS__DB_H : AM_3R<0x385a8000>; 999def AMCAS__DB_W : AM_3R<0x385b0000>; 1000def AMCAS__DB_D : AM_3R<0x385b8000>; 1001def LL_D : LLBase<0x22000000>; 1002def SC_D : SCBase<0x23000000>; 1003def SC_Q : SCBase_128<0x38570000>; 1004def LLACQ_D : LLBase_ACQ<0x38578800>; 1005def SCREL_D : SCBase_REL<0x38578C00>; 1006 1007// CRC Check Instructions 1008def CRC_W_B_W : ALU_3R<0x00240000>; 1009def CRC_W_H_W : ALU_3R<0x00248000>; 1010def CRC_W_W_W : ALU_3R<0x00250000>; 1011def CRC_W_D_W : ALU_3R<0x00258000>; 1012def CRCC_W_B_W : ALU_3R<0x00260000>; 1013def CRCC_W_H_W : ALU_3R<0x00268000>; 1014def CRCC_W_W_W : ALU_3R<0x00270000>; 1015def CRCC_W_D_W : ALU_3R<0x00278000>; 1016 1017// Other Miscellaneous Instructions for 64-bits 1018def ASRTLE_D : FmtASRT<0x00010000, (outs), (ins GPR:$rj, GPR:$rk), 1019 "$rj, $rk">; 1020def ASRTGT_D : FmtASRT<0x00018000, (outs), (ins GPR:$rj, GPR:$rk), 1021 "$rj, $rk">; 1022def RDTIME_D : RDTIME_2R<0x00006800>; 1023} // Predicates = [IsLA64] 1024 1025//===----------------------------------------------------------------------===// 1026// Pseudo-instructions and codegen patterns 1027// 1028// Naming convention: For 'generic' pattern classes, we use the naming 1029// convention PatTy1Ty2. 1030//===----------------------------------------------------------------------===// 1031 1032/// Generic pattern classes 1033 1034class PatGprGpr<SDPatternOperator OpNode, LAInst Inst> 1035 : Pat<(OpNode GPR:$rj, GPR:$rk), (Inst GPR:$rj, GPR:$rk)>; 1036class PatGprGpr_32<SDPatternOperator OpNode, LAInst Inst> 1037 : Pat<(sext_inreg (OpNode GPR:$rj, GPR:$rk), i32), (Inst GPR:$rj, GPR:$rk)>; 1038class PatGpr<SDPatternOperator OpNode, LAInst Inst> 1039 : Pat<(OpNode GPR:$rj), (Inst GPR:$rj)>; 1040 1041class PatGprImm<SDPatternOperator OpNode, LAInst Inst, Operand ImmOpnd> 1042 : Pat<(OpNode GPR:$rj, ImmOpnd:$imm), 1043 (Inst GPR:$rj, ImmOpnd:$imm)>; 1044class PatGprImm_32<SDPatternOperator OpNode, LAInst Inst, Operand ImmOpnd> 1045 : Pat<(sext_inreg (OpNode GPR:$rj, ImmOpnd:$imm), i32), 1046 (Inst GPR:$rj, ImmOpnd:$imm)>; 1047 1048/// Predicates 1049def AddLike: PatFrags<(ops node:$A, node:$B), 1050 [(add node:$A, node:$B), (or node:$A, node:$B)], [{ 1051 return N->getOpcode() == ISD::ADD || isOrEquivalentToAdd(N); 1052}]>; 1053 1054/// Simple arithmetic operations 1055 1056// Match both a plain shift and one where the shift amount is masked (this is 1057// typically introduced when the legalizer promotes the shift amount and 1058// zero-extends it). For LoongArch, the mask is unnecessary as shifts in the 1059// base ISA only read the least significant 5 bits (LA32) or 6 bits (LA64). 1060def shiftMaskGRLen 1061 : ComplexPattern<GRLenVT, 1, "selectShiftMaskGRLen", [], [], 0>; 1062def shiftMask32 : ComplexPattern<i64, 1, "selectShiftMask32", [], [], 0>; 1063 1064def sexti32 : ComplexPattern<i64, 1, "selectSExti32">; 1065def zexti32 : ComplexPattern<i64, 1, "selectZExti32">; 1066 1067class shiftop<SDPatternOperator operator> 1068 : PatFrag<(ops node:$val, node:$count), 1069 (operator node:$val, (GRLenVT (shiftMaskGRLen node:$count)))>; 1070class shiftopw<SDPatternOperator operator> 1071 : PatFrag<(ops node:$val, node:$count), 1072 (operator node:$val, (i64 (shiftMask32 node:$count)))>; 1073 1074def mul_const_oneuse : PatFrag<(ops node:$A, node:$B), 1075 (mul node:$A, node:$B), [{ 1076 if (auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1))) 1077 return N1C->hasOneUse(); 1078 return false; 1079}]>; 1080 1081let Predicates = [IsLA32] in { 1082def : PatGprGpr<add, ADD_W>; 1083def : PatGprImm<add, ADDI_W, simm12>; 1084def : PatGprGpr<sub, SUB_W>; 1085def : PatGprGpr<sdiv, DIV_W>; 1086def : PatGprGpr<udiv, DIV_WU>; 1087def : PatGprGpr<srem, MOD_W>; 1088def : PatGprGpr<urem, MOD_WU>; 1089def : PatGprGpr<mul, MUL_W>; 1090def : PatGprGpr<mulhs, MULH_W>; 1091def : PatGprGpr<mulhu, MULH_WU>; 1092def : PatGprGpr<rotr, ROTR_W>; 1093def : PatGprImm<rotr, ROTRI_W, uimm5>; 1094 1095foreach Idx = 1...3 in { 1096 defvar ShamtA = !mul(8, Idx); 1097 defvar ShamtB = !mul(8, !sub(4, Idx)); 1098 def : Pat<(or (shl GPR:$rk, (i32 ShamtA)), (srl GPR:$rj, (i32 ShamtB))), 1099 (BYTEPICK_W GPR:$rj, GPR:$rk, Idx)>; 1100} 1101} // Predicates = [IsLA32] 1102 1103let Predicates = [IsLA64] in { 1104def : PatGprGpr<add, ADD_D>; 1105def : PatGprGpr_32<add, ADD_W>; 1106def : PatGprImm<add, ADDI_D, simm12>; 1107def : PatGprImm_32<add, ADDI_W, simm12>; 1108def : PatGprGpr<sub, SUB_D>; 1109def : PatGprGpr_32<sub, SUB_W>; 1110def : PatGprGpr<sdiv, DIV_D>; 1111def : PatGprGpr<udiv, DIV_DU>; 1112def : PatGprGpr<srem, MOD_D>; 1113def : PatGprGpr<urem, MOD_DU>; 1114def : PatGprGpr<rotr, ROTR_D>; 1115def : PatGprGpr<loongarch_rotr_w, ROTR_W>; 1116def : PatGprImm<rotr, ROTRI_D, uimm6>; 1117def : PatGprImm_32<rotr, ROTRI_W, uimm5>; 1118def : Pat<(loongarch_rotl_w GPR:$rj, uimm5:$imm), 1119 (ROTRI_W GPR:$rj, (ImmSubFrom32 uimm5:$imm))>; 1120def : Pat<(sext_inreg (loongarch_rotl_w GPR:$rj, uimm5:$imm), i32), 1121 (ROTRI_W GPR:$rj, (ImmSubFrom32 uimm5:$imm))>; 1122// TODO: Select "_W[U]" instructions for i32xi32 if only lower 32 bits of the 1123// product are used. 1124def : PatGprGpr<mul, MUL_D>; 1125def : PatGprGpr<mulhs, MULH_D>; 1126def : PatGprGpr<mulhu, MULH_DU>; 1127// Select MULW_D_W for calculating the full 64 bits product of i32xi32 signed 1128// multiplication. 1129def : Pat<(i64 (mul (sext_inreg GPR:$rj, i32), (sext_inreg GPR:$rk, i32))), 1130 (MULW_D_W GPR:$rj, GPR:$rk)>; 1131// Select MULW_D_WU for calculating the full 64 bits product of i32xi32 1132// unsigned multiplication. 1133def : Pat<(i64 (mul (loongarch_bstrpick GPR:$rj, (i64 31), (i64 0)), 1134 (loongarch_bstrpick GPR:$rk, (i64 31), (i64 0)))), 1135 (MULW_D_WU GPR:$rj, GPR:$rk)>; 1136 1137def : Pat<(add GPR:$rj, simm16_lsl16:$imm), 1138 (ADDU16I_D GPR:$rj, (HI16 $imm))>; 1139def : Pat<(add GPR:$rj, simm32_hi16_lo12:$imm), 1140 (ADDI_D (ADDU16I_D GPR:$rj, (HI16ForAddu16idAddiPair $imm)), 1141 (LO12 $imm))>; 1142def : Pat<(sext_inreg (add GPR:$rj, simm32_hi16_lo12:$imm), i32), 1143 (ADDI_W (ADDU16I_D GPR:$rj, (HI16ForAddu16idAddiPair $imm)), 1144 (LO12 $imm))>; 1145 1146let Predicates = [IsLA32] in { 1147def : Pat<(add GPR:$rj, (AddiPair:$im)), 1148 (ADDI_W (ADDI_W GPR:$rj, (AddiPairImmLarge AddiPair:$im)), 1149 (AddiPairImmSmall AddiPair:$im))>; 1150} // Predicates = [IsLA32] 1151 1152let Predicates = [IsLA64] in { 1153def : Pat<(add GPR:$rj, (AddiPair:$im)), 1154 (ADDI_D (ADDI_D GPR:$rj, (AddiPairImmLarge AddiPair:$im)), 1155 (AddiPairImmSmall AddiPair:$im))>; 1156def : Pat<(sext_inreg (add GPR:$rj, (AddiPair:$im)), i32), 1157 (ADDI_W (ADDI_W GPR:$rj, (AddiPairImmLarge AddiPair:$im)), 1158 (AddiPairImmSmall AddiPair:$im))>; 1159} // Predicates = [IsLA64] 1160 1161let Predicates = [IsLA32] in { 1162foreach Idx0 = 1...4 in { 1163 foreach Idx1 = 1...4 in { 1164 defvar CImm = !add(1, !shl(!add(1, !shl(1, Idx0)), Idx1)); 1165 def : Pat<(mul_const_oneuse GPR:$r, (i32 CImm)), 1166 (ALSL_W (ALSL_W GPR:$r, GPR:$r, (i32 Idx0)), 1167 GPR:$r, (i32 Idx1))>; 1168 } 1169} 1170foreach Idx0 = 1...4 in { 1171 foreach Idx1 = 1...4 in { 1172 defvar Cb = !add(1, !shl(1, Idx0)); 1173 defvar CImm = !add(Cb, !shl(Cb, Idx1)); 1174 def : Pat<(mul_const_oneuse GPR:$r, (i32 CImm)), 1175 (ALSL_W (ALSL_W GPR:$r, GPR:$r, (i32 Idx0)), 1176 (ALSL_W GPR:$r, GPR:$r, (i32 Idx0)), (i32 Idx1))>; 1177 } 1178} 1179} // Predicates = [IsLA32] 1180 1181let Predicates = [IsLA64] in { 1182foreach Idx0 = 1...4 in { 1183 foreach Idx1 = 1...4 in { 1184 defvar CImm = !add(1, !shl(!add(1, !shl(1, Idx0)), Idx1)); 1185 def : Pat<(sext_inreg (mul_const_oneuse GPR:$r, (i64 CImm)), i32), 1186 (ALSL_W (ALSL_W GPR:$r, GPR:$r, (i64 Idx0)), 1187 GPR:$r, (i64 Idx1))>; 1188 def : Pat<(mul_const_oneuse GPR:$r, (i64 CImm)), 1189 (ALSL_D (ALSL_D GPR:$r, GPR:$r, (i64 Idx0)), 1190 GPR:$r, (i64 Idx1))>; 1191 } 1192} 1193foreach Idx0 = 1...4 in { 1194 foreach Idx1 = 1...4 in { 1195 defvar Cb = !add(1, !shl(1, Idx0)); 1196 defvar CImm = !add(Cb, !shl(Cb, Idx1)); 1197 def : Pat<(sext_inreg (mul_const_oneuse GPR:$r, (i64 CImm)), i32), 1198 (ALSL_W (ALSL_W GPR:$r, GPR:$r, (i64 Idx0)), 1199 (ALSL_W GPR:$r, GPR:$r, (i64 Idx0)), (i64 Idx1))>; 1200 def : Pat<(mul_const_oneuse GPR:$r, (i64 CImm)), 1201 (ALSL_D (ALSL_D GPR:$r, GPR:$r, (i64 Idx0)), 1202 (ALSL_D GPR:$r, GPR:$r, (i64 Idx0)), (i64 Idx1))>; 1203 } 1204} 1205} // Predicates = [IsLA64] 1206 1207let Predicates = [IsLA32] in { 1208def : Pat<(mul GPR:$rj, (AlslSlliImm:$im)), 1209 (SLLI_W (ALSL_W GPR:$rj, GPR:$rj, (AlslSlliImmI0 AlslSlliImm:$im)), 1210 (AlslSlliImmI1 AlslSlliImm:$im))>; 1211} // Predicates = [IsLA32] 1212 1213let Predicates = [IsLA64] in { 1214def : Pat<(sext_inreg (mul GPR:$rj, (AlslSlliImm:$im)), i32), 1215 (SLLI_W (ALSL_W GPR:$rj, GPR:$rj, (AlslSlliImmI0 AlslSlliImm:$im)), 1216 (AlslSlliImmI1 AlslSlliImm:$im))>; 1217def : Pat<(mul GPR:$rj, (AlslSlliImm:$im)), 1218 (SLLI_D (ALSL_D GPR:$rj, GPR:$rj, (AlslSlliImmI0 AlslSlliImm:$im)), 1219 (AlslSlliImmI1 AlslSlliImm:$im))>; 1220} // Predicates = [IsLA64] 1221 1222foreach Idx = 1...7 in { 1223 defvar ShamtA = !mul(8, Idx); 1224 defvar ShamtB = !mul(8, !sub(8, Idx)); 1225 def : Pat<(or (shl GPR:$rk, (i64 ShamtA)), (srl GPR:$rj, (i64 ShamtB))), 1226 (BYTEPICK_D GPR:$rj, GPR:$rk, Idx)>; 1227} 1228 1229foreach Idx = 1...3 in { 1230 defvar ShamtA = !mul(8, Idx); 1231 defvar ShamtB = !mul(8, !sub(4, Idx)); 1232 // NOTE: the srl node would already be transformed into a loongarch_bstrpick 1233 // by the time this pattern gets to execute, hence the weird construction. 1234 def : Pat<(sext_inreg (or (shl GPR:$rk, (i64 ShamtA)), 1235 (loongarch_bstrpick GPR:$rj, (i64 31), 1236 (i64 ShamtB))), i32), 1237 (BYTEPICK_W GPR:$rj, GPR:$rk, Idx)>; 1238} 1239} // Predicates = [IsLA64] 1240 1241def : PatGprGpr<and, AND>; 1242def : PatGprImm<and, ANDI, uimm12>; 1243def : PatGprGpr<or, OR>; 1244def : PatGprImm<or, ORI, uimm12>; 1245def : PatGprGpr<xor, XOR>; 1246def : PatGprImm<xor, XORI, uimm12>; 1247def : Pat<(not GPR:$rj), (NOR GPR:$rj, R0)>; 1248def : Pat<(not (or GPR:$rj, GPR:$rk)), (NOR GPR:$rj, GPR:$rk)>; 1249def : Pat<(or GPR:$rj, (not GPR:$rk)), (ORN GPR:$rj, GPR:$rk)>; 1250def : Pat<(and GPR:$rj, (not GPR:$rk)), (ANDN GPR:$rj, GPR:$rk)>; 1251 1252let Predicates = [IsLA32] in { 1253def : Pat<(and GPR:$rj, BstrinsImm:$imm), 1254 (BSTRINS_W GPR:$rj, R0, (BstrinsMsb BstrinsImm:$imm), 1255 (BstrinsLsb BstrinsImm:$imm))>; 1256} // Predicates = [IsLA32] 1257 1258let Predicates = [IsLA64] in { 1259def : Pat<(and GPR:$rj, BstrinsImm:$imm), 1260 (BSTRINS_D GPR:$rj, R0, (BstrinsMsb BstrinsImm:$imm), 1261 (BstrinsLsb BstrinsImm:$imm))>; 1262} // Predicates = [IsLA64] 1263 1264/// Traps 1265 1266// We lower `trap` to `amswap.w rd:$r0, rk:$r1, rj:$r0`, as this is guaranteed 1267// to trap with an INE (non-existent on LA32, explicitly documented to INE on 1268// LA64). And the resulting signal is different from `debugtrap` like on some 1269// other existing ports so programs/porters might have an easier time. 1270def PseudoUNIMP : Pseudo<(outs), (ins), [(trap)]>, 1271 PseudoInstExpansion<(AMSWAP_W R0, R1, R0)>; 1272 1273// We lower `debugtrap` to `break 0`, as this is guaranteed to exist and work, 1274// even for LA32 Primary. Also, because so far the ISA does not provide a 1275// specific trap instruction/kind exclusively for alerting the debugger, 1276// every other project uses the generic immediate of 0 for this. 1277def : Pat<(debugtrap), (BREAK 0)>; 1278 1279/// Bit counting operations 1280 1281let Predicates = [IsLA64] in { 1282def : PatGpr<ctlz, CLZ_D>; 1283def : PatGpr<cttz, CTZ_D>; 1284def : Pat<(ctlz (not GPR:$rj)), (CLO_D GPR:$rj)>; 1285def : Pat<(cttz (not GPR:$rj)), (CTO_D GPR:$rj)>; 1286def : PatGpr<loongarch_clzw, CLZ_W>; 1287def : PatGpr<loongarch_ctzw, CTZ_W>; 1288def : Pat<(loongarch_clzw (not GPR:$rj)), (CLO_W GPR:$rj)>; 1289def : Pat<(loongarch_ctzw (not GPR:$rj)), (CTO_W GPR:$rj)>; 1290} // Predicates = [IsLA64] 1291 1292let Predicates = [IsLA32] in { 1293def : PatGpr<ctlz, CLZ_W>; 1294def : PatGpr<cttz, CTZ_W>; 1295def : Pat<(ctlz (not GPR:$rj)), (CLO_W GPR:$rj)>; 1296def : Pat<(cttz (not GPR:$rj)), (CTO_W GPR:$rj)>; 1297} // Predicates = [IsLA32] 1298 1299/// FrameIndex calculations 1300let Predicates = [IsLA32] in { 1301def : Pat<(AddLike (i32 BaseAddr:$rj), simm12:$imm12), 1302 (ADDI_W (i32 BaseAddr:$rj), simm12:$imm12)>; 1303} // Predicates = [IsLA32] 1304let Predicates = [IsLA64] in { 1305def : Pat<(AddLike (i64 BaseAddr:$rj), simm12:$imm12), 1306 (ADDI_D (i64 BaseAddr:$rj), simm12:$imm12)>; 1307} // Predicates = [IsLA64] 1308 1309/// Shifted addition 1310let Predicates = [IsLA32] in { 1311def : Pat<(add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)), 1312 (ALSL_W GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>; 1313} // Predicates = [IsLA32] 1314let Predicates = [IsLA64] in { 1315def : Pat<(add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)), 1316 (ALSL_D GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>; 1317def : Pat<(sext_inreg (add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)), i32), 1318 (ALSL_W GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>; 1319def : Pat<(loongarch_bstrpick (add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)), 1320 (i64 31), (i64 0)), 1321 (ALSL_WU GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>; 1322} // Predicates = [IsLA64] 1323 1324/// Shift 1325 1326let Predicates = [IsLA32] in { 1327def : PatGprGpr<shiftop<shl>, SLL_W>; 1328def : PatGprGpr<shiftop<sra>, SRA_W>; 1329def : PatGprGpr<shiftop<srl>, SRL_W>; 1330def : PatGprImm<shl, SLLI_W, uimm5>; 1331def : PatGprImm<sra, SRAI_W, uimm5>; 1332def : PatGprImm<srl, SRLI_W, uimm5>; 1333} // Predicates = [IsLA32] 1334 1335let Predicates = [IsLA64] in { 1336def : PatGprGpr<shiftopw<loongarch_sll_w>, SLL_W>; 1337def : PatGprGpr<shiftopw<loongarch_sra_w>, SRA_W>; 1338def : PatGprGpr<shiftopw<loongarch_srl_w>, SRL_W>; 1339def : PatGprGpr<shiftop<shl>, SLL_D>; 1340def : PatGprGpr<shiftop<sra>, SRA_D>; 1341def : PatGprGpr<shiftop<srl>, SRL_D>; 1342def : PatGprImm<shl, SLLI_D, uimm6>; 1343def : PatGprImm<sra, SRAI_D, uimm6>; 1344def : PatGprImm<srl, SRLI_D, uimm6>; 1345} // Predicates = [IsLA64] 1346 1347/// sext and zext 1348 1349def : Pat<(sext_inreg GPR:$rj, i8), (EXT_W_B GPR:$rj)>; 1350def : Pat<(sext_inreg GPR:$rj, i16), (EXT_W_H GPR:$rj)>; 1351 1352let Predicates = [IsLA64] in { 1353def : Pat<(sext_inreg GPR:$rj, i32), (ADDI_W GPR:$rj, 0)>; 1354} // Predicates = [IsLA64] 1355 1356/// Setcc 1357 1358def : PatGprGpr<setlt, SLT>; 1359def : PatGprImm<setlt, SLTI, simm12>; 1360def : PatGprGpr<setult, SLTU>; 1361def : PatGprImm<setult, SLTUI, simm12>; 1362 1363// Define pattern expansions for setcc operations that aren't directly 1364// handled by a LoongArch instruction. 1365def : Pat<(seteq GPR:$rj, 0), (SLTUI GPR:$rj, 1)>; 1366def : Pat<(seteq GPR:$rj, GPR:$rk), (SLTUI (XOR GPR:$rj, GPR:$rk), 1)>; 1367let Predicates = [IsLA32] in { 1368def : Pat<(seteq GPR:$rj, simm12_plus1:$imm12), 1369 (SLTUI (ADDI_W GPR:$rj, (NegImm simm12_plus1:$imm12)), 1)>; 1370} // Predicates = [IsLA32] 1371let Predicates = [IsLA64] in { 1372def : Pat<(seteq GPR:$rj, simm12_plus1:$imm12), 1373 (SLTUI (ADDI_D GPR:$rj, (NegImm simm12_plus1:$imm12)), 1)>; 1374} // Predicates = [IsLA64] 1375def : Pat<(setne GPR:$rj, 0), (SLTU R0, GPR:$rj)>; 1376def : Pat<(setne GPR:$rj, GPR:$rk), (SLTU R0, (XOR GPR:$rj, GPR:$rk))>; 1377let Predicates = [IsLA32] in { 1378def : Pat<(setne GPR:$rj, simm12_plus1:$imm12), 1379 (SLTU R0, (ADDI_W GPR:$rj, (NegImm simm12_plus1:$imm12)))>; 1380} // Predicates = [IsLA32] 1381let Predicates = [IsLA64] in { 1382def : Pat<(setne GPR:$rj, simm12_plus1:$imm12), 1383 (SLTU R0, (ADDI_D GPR:$rj, (NegImm simm12_plus1:$imm12)))>; 1384} // Predicates = [IsLA64] 1385def : Pat<(setugt GPR:$rj, GPR:$rk), (SLTU GPR:$rk, GPR:$rj)>; 1386def : Pat<(setuge GPR:$rj, GPR:$rk), (XORI (SLTU GPR:$rj, GPR:$rk), 1)>; 1387def : Pat<(setule GPR:$rj, GPR:$rk), (XORI (SLTU GPR:$rk, GPR:$rj), 1)>; 1388def : Pat<(setgt GPR:$rj, GPR:$rk), (SLT GPR:$rk, GPR:$rj)>; 1389def : Pat<(setge GPR:$rj, GPR:$rk), (XORI (SLT GPR:$rj, GPR:$rk), 1)>; 1390def : Pat<(setle GPR:$rj, GPR:$rk), (XORI (SLT GPR:$rk, GPR:$rj), 1)>; 1391 1392/// Select 1393 1394def : Pat<(select GPR:$cond, GPR:$t, 0), (MASKEQZ GPR:$t, GPR:$cond)>; 1395def : Pat<(select GPR:$cond, 0, GPR:$f), (MASKNEZ GPR:$f, GPR:$cond)>; 1396def : Pat<(select GPR:$cond, GPR:$t, GPR:$f), 1397 (OR (MASKEQZ GPR:$t, GPR:$cond), (MASKNEZ GPR:$f, GPR:$cond))>; 1398 1399/// Branches and jumps 1400 1401class BccPat<PatFrag CondOp, LAInst Inst> 1402 : Pat<(brcond (GRLenVT (CondOp GPR:$rj, GPR:$rd)), bb:$imm16), 1403 (Inst GPR:$rj, GPR:$rd, bb:$imm16)>; 1404 1405def : BccPat<seteq, BEQ>; 1406def : BccPat<setne, BNE>; 1407def : BccPat<setlt, BLT>; 1408def : BccPat<setge, BGE>; 1409def : BccPat<setult, BLTU>; 1410def : BccPat<setuge, BGEU>; 1411 1412class BccSwapPat<PatFrag CondOp, LAInst InstBcc> 1413 : Pat<(brcond (GRLenVT (CondOp GPR:$rd, GPR:$rj)), bb:$imm16), 1414 (InstBcc GPR:$rj, GPR:$rd, bb:$imm16)>; 1415 1416// Condition codes that don't have matching LoongArch branch instructions, but 1417// are trivially supported by swapping the two input operands. 1418def : BccSwapPat<setgt, BLT>; 1419def : BccSwapPat<setle, BGE>; 1420def : BccSwapPat<setugt, BLTU>; 1421def : BccSwapPat<setule, BGEU>; 1422 1423// An extra pattern is needed for a brcond without a setcc (i.e. where the 1424// condition was calculated elsewhere). 1425def : Pat<(brcond GPR:$rj, bb:$imm21), (BNEZ GPR:$rj, bb:$imm21)>; 1426 1427def : Pat<(brcond (GRLenVT (seteq GPR:$rj, 0)), bb:$imm21), 1428 (BEQZ GPR:$rj, bb:$imm21)>; 1429def : Pat<(brcond (GRLenVT (setne GPR:$rj, 0)), bb:$imm21), 1430 (BNEZ GPR:$rj, bb:$imm21)>; 1431 1432let isBarrier = 1, isBranch = 1, isTerminator = 1 in 1433def PseudoBR : Pseudo<(outs), (ins simm26_b:$imm26), [(br bb:$imm26)]>, 1434 PseudoInstExpansion<(B simm26_b:$imm26)>; 1435 1436let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in 1437def PseudoBRIND : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>, 1438 PseudoInstExpansion<(JIRL R0, GPR:$rj, simm16_lsl2:$imm16)>; 1439 1440def : Pat<(brind GPR:$rj), (PseudoBRIND GPR:$rj, 0)>; 1441def : Pat<(brind (add GPR:$rj, simm16_lsl2:$imm16)), 1442 (PseudoBRIND GPR:$rj, simm16_lsl2:$imm16)>; 1443 1444// Function call with 'Small' code model. 1445let isCall = 1, Defs = [R1] in 1446def PseudoCALL : Pseudo<(outs), (ins bare_symbol:$func)>; 1447 1448def : Pat<(loongarch_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>; 1449def : Pat<(loongarch_call texternalsym:$func), (PseudoCALL texternalsym:$func)>; 1450 1451// Function call with 'Medium' code model. 1452let isCall = 1, Defs = [R1, R20], Size = 8 in 1453def PseudoCALL_MEDIUM : Pseudo<(outs), (ins bare_symbol:$func)>; 1454 1455let Predicates = [IsLA64] in { 1456def : Pat<(loongarch_call_medium tglobaladdr:$func), 1457 (PseudoCALL_MEDIUM tglobaladdr:$func)>; 1458def : Pat<(loongarch_call_medium texternalsym:$func), 1459 (PseudoCALL_MEDIUM texternalsym:$func)>; 1460} // Predicates = [IsLA64] 1461 1462// Function call with 'Large' code model. 1463let isCall = 1, Defs = [R1, R20], Size = 24 in 1464def PseudoCALL_LARGE: Pseudo<(outs), (ins bare_symbol:$func)>; 1465 1466let Predicates = [IsLA64] in { 1467def : Pat<(loongarch_call_large tglobaladdr:$func), 1468 (PseudoCALL_LARGE tglobaladdr:$func)>; 1469def : Pat<(loongarch_call_large texternalsym:$func), 1470 (PseudoCALL_LARGE texternalsym:$func)>; 1471} // Predicates = [IsLA64] 1472 1473let isCall = 1, Defs = [R1] in 1474def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rj), 1475 [(loongarch_call GPR:$rj)]>, 1476 PseudoInstExpansion<(JIRL R1, GPR:$rj, 0)>; 1477let Predicates = [IsLA64] in { 1478def : Pat<(loongarch_call_medium GPR:$rj), (PseudoCALLIndirect GPR:$rj)>; 1479def : Pat<(loongarch_call_large GPR:$rj), (PseudoCALLIndirect GPR:$rj)>; 1480} 1481 1482let isCall = 1, hasSideEffects = 0, mayStore = 0, mayLoad = 0, Defs = [R1] in 1483def PseudoJIRL_CALL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>, 1484 PseudoInstExpansion<(JIRL R1, GPR:$rj, 1485 simm16_lsl2:$imm16)>; 1486 1487let isBarrier = 1, isReturn = 1, isTerminator = 1 in 1488def PseudoRET : Pseudo<(outs), (ins), [(loongarch_ret)]>, 1489 PseudoInstExpansion<(JIRL R0, R1, 0)>; 1490 1491// Tail call with 'Small' code model. 1492let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in 1493def PseudoTAIL : Pseudo<(outs), (ins bare_symbol:$dst)>; 1494 1495def : Pat<(loongarch_tail (iPTR tglobaladdr:$dst)), 1496 (PseudoTAIL tglobaladdr:$dst)>; 1497def : Pat<(loongarch_tail (iPTR texternalsym:$dst)), 1498 (PseudoTAIL texternalsym:$dst)>; 1499 1500// Tail call with 'Medium' code model. 1501let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, 1502 Uses = [R3], Defs = [R20], Size = 8 in 1503def PseudoTAIL_MEDIUM : Pseudo<(outs), (ins bare_symbol:$dst)>; 1504 1505let Predicates = [IsLA64] in { 1506def : Pat<(loongarch_tail_medium (iPTR tglobaladdr:$dst)), 1507 (PseudoTAIL_MEDIUM tglobaladdr:$dst)>; 1508def : Pat<(loongarch_tail_medium (iPTR texternalsym:$dst)), 1509 (PseudoTAIL_MEDIUM texternalsym:$dst)>; 1510} // Predicates = [IsLA64] 1511 1512// Tail call with 'Large' code model. 1513let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, 1514 Uses = [R3], Defs = [R19, R20], Size = 24 in 1515def PseudoTAIL_LARGE : Pseudo<(outs), (ins bare_symbol:$dst)>; 1516 1517let Predicates = [IsLA64] in { 1518def : Pat<(loongarch_tail_large (iPTR tglobaladdr:$dst)), 1519 (PseudoTAIL_LARGE tglobaladdr:$dst)>; 1520def : Pat<(loongarch_tail_large (iPTR texternalsym:$dst)), 1521 (PseudoTAIL_LARGE texternalsym:$dst)>; 1522} // Predicates = [IsLA64] 1523 1524let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in 1525def PseudoTAILIndirect : Pseudo<(outs), (ins GPRT:$rj), 1526 [(loongarch_tail GPRT:$rj)]>, 1527 PseudoInstExpansion<(JIRL R0, GPR:$rj, 0)>; 1528let Predicates = [IsLA64] in { 1529def : Pat<(loongarch_tail_medium GPR:$rj), (PseudoTAILIndirect GPR:$rj)>; 1530def : Pat<(loongarch_tail_large GPR:$rj), (PseudoTAILIndirect GPR:$rj)>; 1531} 1532 1533let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, 1534 hasSideEffects = 0, mayStore = 0, mayLoad = 0, Uses = [R3] in 1535def PseudoB_TAIL : Pseudo<(outs), (ins simm26_b:$imm26)>, 1536 PseudoInstExpansion<(B simm26_b:$imm26)>; 1537 1538let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, 1539 hasSideEffects = 0, mayStore = 0, mayLoad = 0, Uses = [R3] in 1540def PseudoJIRL_TAIL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>, 1541 PseudoInstExpansion<(JIRL R0, GPR:$rj, 1542 simm16_lsl2:$imm16)>; 1543 1544/// call36/taill36 macro instructions 1545let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, isAsmParserOnly = 1, 1546 Defs = [R1], Size = 8, hasSideEffects = 0, mayStore = 0, mayLoad = 0 in 1547def PseudoCALL36 : Pseudo<(outs), (ins bare_symbol:$dst), [], 1548 "call36", "$dst">, 1549 Requires<[IsLA64]>; 1550let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3], 1551 isCodeGenOnly = 0, isAsmParserOnly = 1, Size = 8, hasSideEffects = 0, 1552 mayStore = 0, mayLoad = 0 in 1553def PseudoTAIL36 : Pseudo<(outs), (ins GPR:$tmp, bare_symbol:$dst), [], 1554 "tail36", "$tmp, $dst">, 1555 Requires<[IsLA64]>; 1556 1557/// Load address (la*) macro instructions. 1558 1559// Define isCodeGenOnly = 0 to expose them to tablegened assembly parser. 1560let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0, 1561 isAsmParserOnly = 1 in { 1562def PseudoLA_ABS : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1563 "la.abs", "$dst, $src">; 1564def PseudoLA_ABS_LARGE : Pseudo<(outs GPR:$dst), 1565 (ins GPR:$tmp, bare_symbol:$src), [], 1566 "la.abs", "$dst, $src">; 1567def PseudoLA_PCREL : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1568 "la.pcrel", "$dst, $src">; 1569let Defs = [R20], Size = 20 in 1570def PseudoLA_PCREL_LARGE : Pseudo<(outs GPR:$dst), 1571 (ins GPR:$tmp, bare_symbol:$src), [], 1572 "la.pcrel", "$dst, $tmp, $src">, 1573 Requires<[IsLA64]>; 1574def PseudoLA_TLS_LE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1575 "la.tls.le", "$dst, $src">; 1576} 1577let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0, 1578 isAsmParserOnly = 1 in { 1579def PseudoLA_GOT : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1580 "la.got", "$dst, $src">; 1581def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1582 "la.tls.ie", "$dst, $src">; 1583def PseudoLA_TLS_LD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1584 "la.tls.ld", "$dst, $src">; 1585def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1586 "la.tls.gd", "$dst, $src">; 1587let Defs = [R20], Size = 20 in { 1588def PseudoLA_GOT_LARGE : Pseudo<(outs GPR:$dst), 1589 (ins GPR:$tmp, bare_symbol:$src), [], 1590 "la.got", "$dst, $tmp, $src">, 1591 Requires<[IsLA64]>; 1592def PseudoLA_TLS_IE_LARGE : Pseudo<(outs GPR:$dst), 1593 (ins GPR:$tmp, bare_symbol:$src), [], 1594 "la.tls.ie", "$dst, $tmp, $src">, 1595 Requires<[IsLA64]>; 1596def PseudoLA_TLS_LD_LARGE : Pseudo<(outs GPR:$dst), 1597 (ins GPR:$tmp, bare_symbol:$src), [], 1598 "la.tls.ld", "$dst, $tmp, $src">, 1599 Requires<[IsLA64]>; 1600def PseudoLA_TLS_GD_LARGE : Pseudo<(outs GPR:$dst), 1601 (ins GPR:$tmp, bare_symbol:$src), [], 1602 "la.tls.gd", "$dst, $tmp, $src">, 1603 Requires<[IsLA64]>; 1604} // Defs = [R20], Size = 20 1605} 1606 1607// Load address inst alias: "la", "la.global" and "la.local". 1608// Default: 1609// la = la.global = la.got 1610// la.local = la.pcrel 1611// With feature "+la-global-with-pcrel": 1612// la = la.global = la.pcrel 1613// With feature "+la-global-with-abs": 1614// la = la.global = la.abs 1615// With feature "+la-local-with-abs": 1616// la.local = la.abs 1617// With features "+la-global-with-pcrel,+la-global-with-abs"(disorder): 1618// la = la.global = la.pcrel 1619// Note: To keep consistent with gnu-as behavior, the "la" can only have one 1620// register operand. 1621def : InstAlias<"la $dst, $src", (PseudoLA_GOT GPR:$dst, bare_symbol:$src)>; 1622def : InstAlias<"la.global $dst, $src", 1623 (PseudoLA_GOT GPR:$dst, bare_symbol:$src)>; 1624def : InstAlias<"la.global $dst, $tmp, $src", 1625 (PseudoLA_GOT_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>; 1626def : InstAlias<"la.local $dst, $src", 1627 (PseudoLA_PCREL GPR:$dst, bare_symbol:$src)>; 1628def : InstAlias<"la.local $dst, $tmp, $src", 1629 (PseudoLA_PCREL_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>; 1630 1631// Note: Keep HasLaGlobalWithPcrel before HasLaGlobalWithAbs to ensure 1632// "la-global-with-pcrel" takes effect when bose "la-global-with-pcrel" and 1633// "la-global-with-abs" are enabled. 1634let Predicates = [HasLaGlobalWithPcrel] in { 1635def : InstAlias<"la $dst, $src", (PseudoLA_PCREL GPR:$dst, bare_symbol:$src)>; 1636def : InstAlias<"la.global $dst, $src", 1637 (PseudoLA_PCREL GPR:$dst, bare_symbol:$src)>; 1638def : InstAlias<"la.global $dst, $tmp, $src", 1639 (PseudoLA_PCREL_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>; 1640} // Predicates = [HasLaGlobalWithPcrel] 1641 1642let Predicates = [HasLaGlobalWithAbs] in { 1643def : InstAlias<"la $dst, $src", (PseudoLA_ABS GPR:$dst, bare_symbol:$src)>; 1644def : InstAlias<"la.global $dst, $src", 1645 (PseudoLA_ABS GPR:$dst, bare_symbol:$src)>; 1646def : InstAlias<"la.global $dst, $tmp, $src", 1647 (PseudoLA_ABS_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>; 1648} // Predicates = [HasLaGlobalWithAbs] 1649 1650let Predicates = [HasLaLocalWithAbs] in { 1651def : InstAlias<"la.local $dst, $src", 1652 (PseudoLA_ABS GPR:$dst, bare_symbol:$src)>; 1653def : InstAlias<"la.local $dst, $tmp, $src", 1654 (PseudoLA_ABS_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>; 1655} // Predicates = [HasLaLocalWithAbs] 1656 1657/// BSTRINS and BSTRPICK 1658 1659let Predicates = [IsLA32] in { 1660def : Pat<(loongarch_bstrins GPR:$rd, GPR:$rj, uimm5:$msbd, uimm5:$lsbd), 1661 (BSTRINS_W GPR:$rd, GPR:$rj, uimm5:$msbd, uimm5:$lsbd)>; 1662def : Pat<(loongarch_bstrpick GPR:$rj, uimm5:$msbd, uimm5:$lsbd), 1663 (BSTRPICK_W GPR:$rj, uimm5:$msbd, uimm5:$lsbd)>; 1664} // Predicates = [IsLA32] 1665 1666let Predicates = [IsLA64] in { 1667def : Pat<(loongarch_bstrins GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd), 1668 (BSTRINS_D GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>; 1669def : Pat<(loongarch_bstrpick GPR:$rj, uimm6:$msbd, uimm6:$lsbd), 1670 (BSTRPICK_D GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>; 1671} // Predicates = [IsLA64] 1672 1673/// Byte-swapping and bit-reversal 1674 1675def : Pat<(loongarch_revb_2h GPR:$rj), (REVB_2H GPR:$rj)>; 1676def : Pat<(loongarch_bitrev_4b GPR:$rj), (BITREV_4B GPR:$rj)>; 1677 1678let Predicates = [IsLA32] in { 1679def : Pat<(bswap GPR:$rj), (ROTRI_W (REVB_2H GPR:$rj), 16)>; 1680def : Pat<(bitreverse GPR:$rj), (BITREV_W GPR:$rj)>; 1681def : Pat<(bswap (bitreverse GPR:$rj)), (BITREV_4B GPR:$rj)>; 1682def : Pat<(bitreverse (bswap GPR:$rj)), (BITREV_4B GPR:$rj)>; 1683} // Predicates = [IsLA32] 1684 1685let Predicates = [IsLA64] in { 1686def : Pat<(loongarch_revb_2w GPR:$rj), (REVB_2W GPR:$rj)>; 1687def : Pat<(bswap GPR:$rj), (REVB_D GPR:$rj)>; 1688def : Pat<(loongarch_bitrev_w GPR:$rj), (BITREV_W GPR:$rj)>; 1689def : Pat<(bitreverse GPR:$rj), (BITREV_D GPR:$rj)>; 1690def : Pat<(bswap (bitreverse GPR:$rj)), (BITREV_8B GPR:$rj)>; 1691def : Pat<(bitreverse (bswap GPR:$rj)), (BITREV_8B GPR:$rj)>; 1692} // Predicates = [IsLA64] 1693 1694/// Loads 1695 1696multiclass LdPat<PatFrag LoadOp, LAInst Inst, ValueType vt = GRLenVT> { 1697 def : Pat<(vt (LoadOp BaseAddr:$rj)), (Inst BaseAddr:$rj, 0)>; 1698 def : Pat<(vt (LoadOp (AddrConstant GPR:$rj, simm12:$imm12))), 1699 (Inst GPR:$rj, simm12:$imm12)>; 1700 def : Pat<(vt (LoadOp (AddLike BaseAddr:$rj, simm12:$imm12))), 1701 (Inst BaseAddr:$rj, simm12:$imm12)>; 1702} 1703 1704defm : LdPat<sextloadi8, LD_B>; 1705defm : LdPat<extloadi8, LD_B>; 1706defm : LdPat<sextloadi16, LD_H>; 1707defm : LdPat<extloadi16, LD_H>; 1708defm : LdPat<load, LD_W>, Requires<[IsLA32]>; 1709defm : LdPat<zextloadi8, LD_BU>; 1710defm : LdPat<zextloadi16, LD_HU>; 1711let Predicates = [IsLA64] in { 1712defm : LdPat<sextloadi32, LD_W, i64>; 1713defm : LdPat<extloadi32, LD_W, i64>; 1714defm : LdPat<zextloadi32, LD_WU, i64>; 1715defm : LdPat<load, LD_D, i64>; 1716} // Predicates = [IsLA64] 1717 1718// LA64 register-register-addressed loads 1719let Predicates = [IsLA64] in { 1720class RegRegLdPat<PatFrag LoadOp, LAInst Inst, ValueType vt> 1721 : Pat<(vt (LoadOp (add NonFIBaseAddr:$rj, GPR:$rk))), 1722 (Inst NonFIBaseAddr:$rj, GPR:$rk)>; 1723 1724def : RegRegLdPat<extloadi8, LDX_B, i64>; 1725def : RegRegLdPat<sextloadi8, LDX_B, i64>; 1726def : RegRegLdPat<zextloadi8, LDX_BU, i64>; 1727def : RegRegLdPat<extloadi16, LDX_H, i64>; 1728def : RegRegLdPat<sextloadi16, LDX_H, i64>; 1729def : RegRegLdPat<zextloadi16, LDX_HU, i64>; 1730def : RegRegLdPat<extloadi32, LDX_W, i64>; 1731def : RegRegLdPat<sextloadi32, LDX_W, i64>; 1732def : RegRegLdPat<zextloadi32, LDX_WU, i64>; 1733def : RegRegLdPat<load, LDX_D, i64>; 1734} // Predicates = [IsLA64] 1735 1736/// Stores 1737 1738multiclass StPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy, 1739 ValueType vt> { 1740 def : Pat<(StoreOp (vt StTy:$rd), BaseAddr:$rj), 1741 (Inst StTy:$rd, BaseAddr:$rj, 0)>; 1742 def : Pat<(StoreOp (vt StTy:$rs2), (AddrConstant GPR:$rj, simm12:$imm12)), 1743 (Inst StTy:$rs2, GPR:$rj, simm12:$imm12)>; 1744 def : Pat<(StoreOp (vt StTy:$rd), (AddLike BaseAddr:$rj, simm12:$imm12)), 1745 (Inst StTy:$rd, BaseAddr:$rj, simm12:$imm12)>; 1746} 1747 1748defm : StPat<truncstorei8, ST_B, GPR, GRLenVT>; 1749defm : StPat<truncstorei16, ST_H, GPR, GRLenVT>; 1750defm : StPat<store, ST_W, GPR, i32>, Requires<[IsLA32]>; 1751let Predicates = [IsLA64] in { 1752defm : StPat<truncstorei32, ST_W, GPR, i64>; 1753defm : StPat<store, ST_D, GPR, i64>; 1754} // Predicates = [IsLA64] 1755 1756let Predicates = [IsLA64] in { 1757def : Pat<(i64 (sextloadi32 (AddLike BaseAddr:$rj, simm14_lsl2:$imm14))), 1758 (LDPTR_W BaseAddr:$rj, simm14_lsl2:$imm14)>; 1759def : Pat<(i64 (load (AddLike BaseAddr:$rj, simm14_lsl2:$imm14))), 1760 (LDPTR_D BaseAddr:$rj, simm14_lsl2:$imm14)>; 1761def : Pat<(truncstorei32 (i64 GPR:$rd), 1762 (AddLike BaseAddr:$rj, simm14_lsl2:$imm14)), 1763 (STPTR_W GPR:$rd, BaseAddr:$rj, simm14_lsl2:$imm14)>; 1764def : Pat<(store (i64 GPR:$rd), (AddLike BaseAddr:$rj, simm14_lsl2:$imm14)), 1765 (STPTR_D GPR:$rd, BaseAddr:$rj, simm14_lsl2:$imm14)>; 1766} // Predicates = [IsLA64] 1767 1768// LA64 register-register-addressed stores 1769let Predicates = [IsLA64] in { 1770class RegRegStPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy, 1771 ValueType vt> 1772 : Pat<(StoreOp (vt StTy:$rd), (add NonFIBaseAddr:$rj, GPR:$rk)), 1773 (Inst StTy:$rd, NonFIBaseAddr:$rj, GPR:$rk)>; 1774 1775def : RegRegStPat<truncstorei8, STX_B, GPR, i64>; 1776def : RegRegStPat<truncstorei16, STX_H, GPR, i64>; 1777def : RegRegStPat<truncstorei32, STX_W, GPR, i64>; 1778def : RegRegStPat<store, STX_D, GPR, i64>; 1779} // Predicates = [IsLA64] 1780 1781/// Atomic loads and stores 1782 1783// DBAR hint encoding for LA664 and later micro-architectures, paraphrased from 1784// the Linux patch revealing it [1]: 1785// 1786// - Bit 4: kind of constraint (0: completion, 1: ordering) 1787// - Bit 3: barrier for previous read (0: true, 1: false) 1788// - Bit 2: barrier for previous write (0: true, 1: false) 1789// - Bit 1: barrier for succeeding read (0: true, 1: false) 1790// - Bit 0: barrier for succeeding write (0: true, 1: false) 1791// 1792// Hint 0x700: barrier for "read after read" from the same address, which is 1793// e.g. needed by LL-SC loops on older models. (DBAR 0x700 behaves the same as 1794// nop if such reordering is disabled on supporting newer models.) 1795// 1796// [1]: https://lore.kernel.org/loongarch/20230516124536.535343-1-chenhuacai@loongson.cn/ 1797// 1798// Implementations without support for the finer-granularity hints simply treat 1799// all as the full barrier (DBAR 0), so we can unconditionally start emiting the 1800// more precise hints right away. 1801 1802def : Pat<(atomic_fence 4, timm), (DBAR 0b10100)>; // acquire 1803def : Pat<(atomic_fence 5, timm), (DBAR 0b10010)>; // release 1804def : Pat<(atomic_fence 6, timm), (DBAR 0b10000)>; // acqrel 1805def : Pat<(atomic_fence 7, timm), (DBAR 0b10000)>; // seqcst 1806 1807defm : LdPat<atomic_load_8, LD_B>; 1808defm : LdPat<atomic_load_16, LD_H>; 1809defm : LdPat<atomic_load_32, LD_W>; 1810 1811class release_seqcst_store<PatFrag base> 1812 : PatFrag<(ops node:$val, node:$ptr), (base node:$val, node:$ptr), [{ 1813 AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getSuccessOrdering(); 1814 return isReleaseOrStronger(Ordering); 1815}]>; 1816 1817class unordered_monotonic_store<PatFrag base> 1818 : PatFrag<(ops node:$val, node:$ptr), (base node:$val, node:$ptr), [{ 1819 AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getSuccessOrdering(); 1820 return !isReleaseOrStronger(Ordering); 1821}]>; 1822 1823def atomic_store_release_seqcst_32 : release_seqcst_store<atomic_store_32>; 1824def atomic_store_release_seqcst_64 : release_seqcst_store<atomic_store_64>; 1825def atomic_store_unordered_monotonic_32 1826 : unordered_monotonic_store<atomic_store_32>; 1827def atomic_store_unordered_monotonic_64 1828 : unordered_monotonic_store<atomic_store_64>; 1829 1830defm : StPat<atomic_store_8, ST_B, GPR, GRLenVT>; 1831defm : StPat<atomic_store_16, ST_H, GPR, GRLenVT>; 1832defm : StPat<atomic_store_unordered_monotonic_32, ST_W, GPR, i32>, 1833 Requires<[IsLA32]>; 1834 1835def PseudoAtomicStoreW 1836 : Pseudo<(outs GPR:$dst), (ins GPR:$rk, GPR:$rj)>, 1837 PseudoInstExpansion<(AMSWAP__DB_W R0, GPR:$rk, GPRMemAtomic:$rj)>; 1838 1839def : Pat<(atomic_store_release_seqcst_32 GPR:$rj, GPR:$rk), 1840 (PseudoAtomicStoreW GPR:$rj, GPR:$rk)>; 1841 1842let Predicates = [IsLA64] in { 1843def PseudoAtomicStoreD 1844 : Pseudo<(outs GPR:$dst), (ins GPR:$rk, GPR:$rj)>, 1845 PseudoInstExpansion<(AMSWAP__DB_D R0, GPR:$rk, GPRMemAtomic:$rj)>; 1846 1847def : Pat<(atomic_store_release_seqcst_64 GPR:$rj, GPR:$rk), 1848 (PseudoAtomicStoreD GPR:$rj, GPR:$rk)>; 1849 1850defm : LdPat<atomic_load_64, LD_D>; 1851defm : StPat<atomic_store_unordered_monotonic_32, ST_W, GPR, i64>; 1852defm : StPat<atomic_store_unordered_monotonic_64, ST_D, GPR, i64>; 1853} // Predicates = [IsLA64] 1854 1855/// Atomic Ops 1856 1857class PseudoMaskedAM 1858 : Pseudo<(outs GPR:$res, GPR:$scratch), 1859 (ins GPR:$addr, GPR:$incr, GPR:$mask, grlenimm:$ordering)> { 1860 let Constraints = "@earlyclobber $res,@earlyclobber $scratch"; 1861 let mayLoad = 1; 1862 let mayStore = 1; 1863 let hasSideEffects = 0; 1864 let Size = 36; 1865} 1866 1867def PseudoMaskedAtomicSwap32 : PseudoMaskedAM; 1868def PseudoMaskedAtomicLoadAdd32 : PseudoMaskedAM; 1869def PseudoMaskedAtomicLoadSub32 : PseudoMaskedAM; 1870def PseudoMaskedAtomicLoadNand32 : PseudoMaskedAM; 1871 1872class PseudoAM : Pseudo<(outs GPR:$res, GPR:$scratch), 1873 (ins GPR:$addr, GPR:$incr, grlenimm:$ordering)> { 1874 let Constraints = "@earlyclobber $res,@earlyclobber $scratch"; 1875 let mayLoad = 1; 1876 let mayStore = 1; 1877 let hasSideEffects = 0; 1878 let Size = 24; 1879} 1880 1881def PseudoAtomicSwap32 : PseudoAM; 1882def PseudoAtomicLoadNand32 : PseudoAM; 1883def PseudoAtomicLoadNand64 : PseudoAM; 1884def PseudoAtomicLoadAdd32 : PseudoAM; 1885def PseudoAtomicLoadSub32 : PseudoAM; 1886def PseudoAtomicLoadAnd32 : PseudoAM; 1887def PseudoAtomicLoadOr32 : PseudoAM; 1888def PseudoAtomicLoadXor32 : PseudoAM; 1889 1890multiclass PseudoBinPat<string Op, Pseudo BinInst> { 1891 def : Pat<(!cast<PatFrag>(Op#"_monotonic") GPR:$addr, GPR:$incr), 1892 (BinInst GPR:$addr, GPR:$incr, 2)>; 1893 def : Pat<(!cast<PatFrag>(Op#"_acquire") GPR:$addr, GPR:$incr), 1894 (BinInst GPR:$addr, GPR:$incr, 4)>; 1895 def : Pat<(!cast<PatFrag>(Op#"_release") GPR:$addr, GPR:$incr), 1896 (BinInst GPR:$addr, GPR:$incr, 5)>; 1897 def : Pat<(!cast<PatFrag>(Op#"_acq_rel") GPR:$addr, GPR:$incr), 1898 (BinInst GPR:$addr, GPR:$incr, 6)>; 1899 def : Pat<(!cast<PatFrag>(Op#"_seq_cst") GPR:$addr, GPR:$incr), 1900 (BinInst GPR:$addr, GPR:$incr, 7)>; 1901} 1902 1903class PseudoMaskedAMUMinUMax 1904 : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2), 1905 (ins GPR:$addr, GPR:$incr, GPR:$mask, grlenimm:$ordering)> { 1906 let Constraints = "@earlyclobber $res,@earlyclobber $scratch1," 1907 "@earlyclobber $scratch2"; 1908 let mayLoad = 1; 1909 let mayStore = 1; 1910 let hasSideEffects = 0; 1911 let Size = 48; 1912} 1913 1914def PseudoMaskedAtomicLoadUMax32 : PseudoMaskedAMUMinUMax; 1915def PseudoMaskedAtomicLoadUMin32 : PseudoMaskedAMUMinUMax; 1916 1917class PseudoMaskedAMMinMax 1918 : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2), 1919 (ins GPR:$addr, GPR:$incr, GPR:$mask, grlenimm:$sextshamt, 1920 grlenimm:$ordering)> { 1921 let Constraints = "@earlyclobber $res,@earlyclobber $scratch1," 1922 "@earlyclobber $scratch2"; 1923 let mayLoad = 1; 1924 let mayStore = 1; 1925 let hasSideEffects = 0; 1926 let Size = 56; 1927} 1928 1929def PseudoMaskedAtomicLoadMax32 : PseudoMaskedAMMinMax; 1930def PseudoMaskedAtomicLoadMin32 : PseudoMaskedAMMinMax; 1931 1932/// Compare and exchange 1933 1934class PseudoCmpXchg 1935 : Pseudo<(outs GPR:$res, GPR:$scratch), 1936 (ins GPR:$addr, GPR:$cmpval, GPR:$newval, grlenimm:$fail_order)> { 1937 let Constraints = "@earlyclobber $res,@earlyclobber $scratch"; 1938 let mayLoad = 1; 1939 let mayStore = 1; 1940 let hasSideEffects = 0; 1941 let Size = 36; 1942} 1943 1944def PseudoCmpXchg32 : PseudoCmpXchg; 1945def PseudoCmpXchg64 : PseudoCmpXchg; 1946 1947def PseudoMaskedCmpXchg32 1948 : Pseudo<(outs GPR:$res, GPR:$scratch), 1949 (ins GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, 1950 grlenimm:$fail_order)> { 1951 let Constraints = "@earlyclobber $res,@earlyclobber $scratch"; 1952 let mayLoad = 1; 1953 let mayStore = 1; 1954 let hasSideEffects = 0; 1955 let Size = 44; 1956} 1957 1958class PseudoMaskedAMMinMaxPat<Intrinsic intrin, Pseudo AMInst> 1959 : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt, 1960 timm:$ordering), 1961 (AMInst GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt, 1962 timm:$ordering)>; 1963 1964class AtomicPat<Intrinsic intrin, Pseudo AMInst> 1965 : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering), 1966 (AMInst GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering)>; 1967 1968// These atomic cmpxchg PatFrags only care about the failure ordering. 1969// The PatFrags defined by multiclass `ternary_atomic_op_ord` in 1970// TargetSelectionDAG.td care about the merged memory ordering that is the 1971// stronger one between success and failure. But for LoongArch LL-SC we only 1972// need to care about the failure ordering as explained in PR #67391. So we 1973// define these PatFrags that will be used to define cmpxchg pats below. 1974multiclass ternary_atomic_op_failure_ord { 1975 def NAME#_failure_monotonic : PatFrag<(ops node:$ptr, node:$cmp, node:$val), 1976 (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{ 1977 AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getFailureOrdering(); 1978 return Ordering == AtomicOrdering::Monotonic; 1979 }]>; 1980 def NAME#_failure_acquire : PatFrag<(ops node:$ptr, node:$cmp, node:$val), 1981 (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{ 1982 AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getFailureOrdering(); 1983 return Ordering == AtomicOrdering::Acquire; 1984 }]>; 1985 def NAME#_failure_release : PatFrag<(ops node:$ptr, node:$cmp, node:$val), 1986 (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{ 1987 AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getFailureOrdering(); 1988 return Ordering == AtomicOrdering::Release; 1989 }]>; 1990 def NAME#_failure_acq_rel : PatFrag<(ops node:$ptr, node:$cmp, node:$val), 1991 (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{ 1992 AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getFailureOrdering(); 1993 return Ordering == AtomicOrdering::AcquireRelease; 1994 }]>; 1995 def NAME#_failure_seq_cst : PatFrag<(ops node:$ptr, node:$cmp, node:$val), 1996 (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{ 1997 AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getFailureOrdering(); 1998 return Ordering == AtomicOrdering::SequentiallyConsistent; 1999 }]>; 2000} 2001 2002defm atomic_cmp_swap_32 : ternary_atomic_op_failure_ord; 2003defm atomic_cmp_swap_64 : ternary_atomic_op_failure_ord; 2004 2005let Predicates = [IsLA64] in { 2006def : AtomicPat<int_loongarch_masked_atomicrmw_xchg_i64, 2007 PseudoMaskedAtomicSwap32>; 2008def : Pat<(atomic_swap_32 GPR:$addr, GPR:$incr), 2009 (AMSWAP__DB_W GPR:$incr, GPR:$addr)>; 2010def : Pat<(atomic_swap_64 GPR:$addr, GPR:$incr), 2011 (AMSWAP__DB_D GPR:$incr, GPR:$addr)>; 2012def : Pat<(atomic_load_add_64 GPR:$rj, GPR:$rk), 2013 (AMADD__DB_D GPR:$rk, GPR:$rj)>; 2014def : AtomicPat<int_loongarch_masked_atomicrmw_add_i64, 2015 PseudoMaskedAtomicLoadAdd32>; 2016def : Pat<(atomic_load_sub_32 GPR:$rj, GPR:$rk), 2017 (AMADD__DB_W (SUB_W R0, GPR:$rk), GPR:$rj)>; 2018def : Pat<(atomic_load_sub_64 GPR:$rj, GPR:$rk), 2019 (AMADD__DB_D (SUB_D R0, GPR:$rk), GPR:$rj)>; 2020def : AtomicPat<int_loongarch_masked_atomicrmw_sub_i64, 2021 PseudoMaskedAtomicLoadSub32>; 2022defm : PseudoBinPat<"atomic_load_nand_64", PseudoAtomicLoadNand64>; 2023def : AtomicPat<int_loongarch_masked_atomicrmw_nand_i64, 2024 PseudoMaskedAtomicLoadNand32>; 2025def : Pat<(atomic_load_add_32 GPR:$rj, GPR:$rk), 2026 (AMADD__DB_W GPR:$rk, GPR:$rj)>; 2027def : Pat<(atomic_load_and_32 GPR:$rj, GPR:$rk), 2028 (AMAND__DB_W GPR:$rk, GPR:$rj)>; 2029def : Pat<(atomic_load_and_64 GPR:$rj, GPR:$rk), 2030 (AMAND__DB_D GPR:$rk, GPR:$rj)>; 2031def : Pat<(atomic_load_or_32 GPR:$rj, GPR:$rk), 2032 (AMOR__DB_W GPR:$rk, GPR:$rj)>; 2033def : Pat<(atomic_load_or_64 GPR:$rj, GPR:$rk), 2034 (AMOR__DB_D GPR:$rk, GPR:$rj)>; 2035def : Pat<(atomic_load_xor_32 GPR:$rj, GPR:$rk), 2036 (AMXOR__DB_W GPR:$rk, GPR:$rj)>; 2037def : Pat<(atomic_load_xor_64 GPR:$rj, GPR:$rk), 2038 (AMXOR__DB_D GPR:$rk, GPR:$rj)>; 2039 2040def : Pat<(atomic_load_umin_32 GPR:$rj, GPR:$rk), 2041 (AMMIN__DB_WU GPR:$rk, GPR:$rj)>; 2042def : Pat<(atomic_load_umin_64 GPR:$rj, GPR:$rk), 2043 (AMMIN__DB_DU GPR:$rk, GPR:$rj)>; 2044def : Pat<(atomic_load_umax_32 GPR:$rj, GPR:$rk), 2045 (AMMAX__DB_WU GPR:$rk, GPR:$rj)>; 2046def : Pat<(atomic_load_umax_64 GPR:$rj, GPR:$rk), 2047 (AMMAX__DB_DU GPR:$rk, GPR:$rj)>; 2048 2049def : Pat<(atomic_load_min_32 GPR:$rj, GPR:$rk), 2050 (AMMIN__DB_W GPR:$rk, GPR:$rj)>; 2051def : Pat<(atomic_load_min_64 GPR:$rj, GPR:$rk), 2052 (AMMIN__DB_D GPR:$rk, GPR:$rj)>; 2053def : Pat<(atomic_load_max_32 GPR:$rj, GPR:$rk), 2054 (AMMAX__DB_W GPR:$rk, GPR:$rj)>; 2055def : Pat<(atomic_load_max_64 GPR:$rj, GPR:$rk), 2056 (AMMAX__DB_D GPR:$rk, GPR:$rj)>; 2057 2058def : AtomicPat<int_loongarch_masked_atomicrmw_umax_i64, 2059 PseudoMaskedAtomicLoadUMax32>; 2060def : AtomicPat<int_loongarch_masked_atomicrmw_umin_i64, 2061 PseudoMaskedAtomicLoadUMin32>; 2062 2063// Ordering constants must be kept in sync with the AtomicOrdering enum in 2064// AtomicOrdering.h. 2065multiclass PseudoCmpXchgPat<string Op, Pseudo CmpXchgInst, 2066 ValueType vt = GRLenVT> { 2067 def : Pat<(vt (!cast<PatFrag>(Op#"_failure_monotonic") GPR:$addr, GPR:$cmp, GPR:$new)), 2068 (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 2)>; 2069 def : Pat<(vt (!cast<PatFrag>(Op#"_failure_acquire") GPR:$addr, GPR:$cmp, GPR:$new)), 2070 (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 4)>; 2071 def : Pat<(vt (!cast<PatFrag>(Op#"_failure_release") GPR:$addr, GPR:$cmp, GPR:$new)), 2072 (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 5)>; 2073 def : Pat<(vt (!cast<PatFrag>(Op#"_failure_acq_rel") GPR:$addr, GPR:$cmp, GPR:$new)), 2074 (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 6)>; 2075 def : Pat<(vt (!cast<PatFrag>(Op#"_failure_seq_cst") GPR:$addr, GPR:$cmp, GPR:$new)), 2076 (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 7)>; 2077} 2078 2079defm : PseudoCmpXchgPat<"atomic_cmp_swap_32", PseudoCmpXchg32>; 2080defm : PseudoCmpXchgPat<"atomic_cmp_swap_64", PseudoCmpXchg64, i64>; 2081def : Pat<(int_loongarch_masked_cmpxchg_i64 2082 GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$fail_order), 2083 (PseudoMaskedCmpXchg32 2084 GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$fail_order)>; 2085 2086def : PseudoMaskedAMMinMaxPat<int_loongarch_masked_atomicrmw_max_i64, 2087 PseudoMaskedAtomicLoadMax32>; 2088def : PseudoMaskedAMMinMaxPat<int_loongarch_masked_atomicrmw_min_i64, 2089 PseudoMaskedAtomicLoadMin32>; 2090} // Predicates = [IsLA64] 2091 2092defm : PseudoBinPat<"atomic_load_nand_32", PseudoAtomicLoadNand32>; 2093 2094let Predicates = [IsLA32] in { 2095def : AtomicPat<int_loongarch_masked_atomicrmw_xchg_i32, 2096 PseudoMaskedAtomicSwap32>; 2097defm : PseudoBinPat<"atomic_swap_32", PseudoAtomicSwap32>; 2098def : AtomicPat<int_loongarch_masked_atomicrmw_add_i32, 2099 PseudoMaskedAtomicLoadAdd32>; 2100def : AtomicPat<int_loongarch_masked_atomicrmw_sub_i32, 2101 PseudoMaskedAtomicLoadSub32>; 2102def : AtomicPat<int_loongarch_masked_atomicrmw_nand_i32, 2103 PseudoMaskedAtomicLoadNand32>; 2104defm : PseudoBinPat<"atomic_load_add_32", PseudoAtomicLoadAdd32>; 2105defm : PseudoBinPat<"atomic_load_sub_32", PseudoAtomicLoadSub32>; 2106defm : PseudoBinPat<"atomic_load_and_32", PseudoAtomicLoadAnd32>; 2107defm : PseudoBinPat<"atomic_load_or_32", PseudoAtomicLoadOr32>; 2108defm : PseudoBinPat<"atomic_load_xor_32", PseudoAtomicLoadXor32>; 2109} // Predicates = [IsLA32] 2110 2111/// Intrinsics 2112 2113def : Pat<(int_loongarch_cacop_d timm:$op, i64:$rj, timm:$imm12), 2114 (CACOP timm:$op, GPR:$rj, timm:$imm12)>; 2115def : Pat<(int_loongarch_cacop_w i32:$op, i32:$rj, i32:$imm12), 2116 (CACOP timm:$op, GPR:$rj, timm:$imm12)>; 2117def : Pat<(loongarch_dbar uimm15:$imm15), (DBAR uimm15:$imm15)>; 2118def : Pat<(loongarch_ibar uimm15:$imm15), (IBAR uimm15:$imm15)>; 2119def : Pat<(loongarch_break uimm15:$imm15), (BREAK uimm15:$imm15)>; 2120def : Pat<(loongarch_syscall uimm15:$imm15), (SYSCALL uimm15:$imm15)>; 2121 2122let Predicates = [IsLA64] in { 2123// CRC Check Instructions 2124def : PatGprGpr<loongarch_crc_w_b_w, CRC_W_B_W>; 2125def : PatGprGpr<loongarch_crc_w_h_w, CRC_W_H_W>; 2126def : PatGprGpr<loongarch_crc_w_w_w, CRC_W_W_W>; 2127def : PatGprGpr<loongarch_crc_w_d_w, CRC_W_D_W>; 2128def : PatGprGpr<loongarch_crcc_w_b_w, CRCC_W_B_W>; 2129def : PatGprGpr<loongarch_crcc_w_h_w, CRCC_W_H_W>; 2130def : PatGprGpr<loongarch_crcc_w_w_w, CRCC_W_W_W>; 2131def : PatGprGpr<loongarch_crcc_w_d_w, CRCC_W_D_W>; 2132} // Predicates = [IsLA64] 2133 2134/// Other pseudo-instructions 2135 2136// Pessimistically assume the stack pointer will be clobbered 2137let Defs = [R3], Uses = [R3] in { 2138def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 2139 [(callseq_start timm:$amt1, timm:$amt2)]>; 2140def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 2141 [(callseq_end timm:$amt1, timm:$amt2)]>; 2142} // Defs = [R3], Uses = [R3] 2143 2144//===----------------------------------------------------------------------===// 2145// Assembler Pseudo Instructions 2146//===----------------------------------------------------------------------===// 2147 2148def : InstAlias<"nop", (ANDI R0, R0, 0)>; 2149def : InstAlias<"move $dst, $src", (OR GPR:$dst, GPR:$src, R0)>; 2150// `ret` is supported since binutils commit 20f2e2686c79a5ac (version 2.40 and 2151// later). 2152def : InstAlias<"ret", (JIRL R0, R1, 0)>; 2153def : InstAlias<"jr $rj", (JIRL R0, GPR:$rj, 0)>; 2154 2155// Branches implemented with alias. 2156// Always output the canonical mnemonic for the pseudo branch instructions. 2157// The GNU tools emit the canonical mnemonic for the branch pseudo instructions 2158// as well (e.g. "bgt" will be recognised by the assembler but never printed by 2159// objdump). Match this behaviour by setting a zero weight. 2160def : InstAlias<"bgt $rj, $rd, $imm16", 2161 (BLT GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>; 2162def : InstAlias<"bgtu $rj, $rd, $imm16", 2163 (BLTU GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>; 2164def : InstAlias<"ble $rj, $rd, $imm16", 2165 (BGE GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>; 2166def : InstAlias<"bleu $rj, $rd, $imm16", 2167 (BGEU GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>; 2168def : InstAlias<"bltz $rd, $imm16", 2169 (BLT GPR:$rd, R0, simm16_lsl2_br:$imm16), 0>; 2170def : InstAlias<"bgtz $rj, $imm16", 2171 (BLT R0, GPR:$rj, simm16_lsl2_br:$imm16), 0>; 2172def : InstAlias<"blez $rj, $imm16", 2173 (BGE R0, GPR:$rj, simm16_lsl2_br:$imm16), 0>; 2174def : InstAlias<"bgez $rd, $imm16", 2175 (BGE GPR:$rd, R0, simm16_lsl2_br:$imm16), 0>; 2176 2177// Load immediate. 2178let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0, 2179 isAsmParserOnly = 1 in { 2180def PseudoLI_W : Pseudo<(outs GPR:$rd), (ins imm32:$imm), [], 2181 "li.w", "$rd, $imm">; 2182def PseudoLI_D : Pseudo<(outs GPR:$rd), (ins grlenimm:$imm), [], 2183 "li.d", "$rd, $imm">, Requires<[IsLA64]>; 2184} 2185 2186//===----------------------------------------------------------------------===// 2187// Basic Floating-Point Instructions 2188//===----------------------------------------------------------------------===// 2189 2190include "LoongArchFloat32InstrInfo.td" 2191include "LoongArchFloat64InstrInfo.td" 2192 2193let Predicates = [HasBasicF], usesCustomInserter = 1 in { 2194 def WRFCSR : Pseudo<(outs), (ins uimm2:$fcsr, GPR:$src), 2195 [(loongarch_movgr2fcsr uimm2:$fcsr, GRLenVT:$src)]>; 2196 def RDFCSR : Pseudo<(outs GPR:$rd), (ins uimm2:$fcsr), 2197 [(set GPR:$rd, (loongarch_movfcsr2gr uimm2:$fcsr))]>; 2198} 2199 2200//===----------------------------------------------------------------------===// 2201// Privilege Instructions 2202//===----------------------------------------------------------------------===// 2203 2204// CSR Access Instructions 2205let hasSideEffects = 1 in 2206def CSRRD : FmtCSR<0x04000000, (outs GPR:$rd), (ins uimm14:$csr_num), 2207 "$rd, $csr_num">; 2208let hasSideEffects = 1, Constraints = "$rd = $dst" in { 2209def CSRWR : FmtCSR<0x04000020, (outs GPR:$dst), 2210 (ins GPR:$rd, uimm14:$csr_num), "$rd, $csr_num">; 2211def CSRXCHG : FmtCSRXCHG<0x04000000, (outs GPR:$dst), 2212 (ins GPR:$rd, GPR:$rj, uimm14:$csr_num), 2213 "$rd, $rj, $csr_num">; 2214} // hasSideEffects = 1, Constraints = "$rd = $dst" 2215 2216// IOCSR Access Instructions 2217def IOCSRRD_B : IOCSRRD<0x06480000>; 2218def IOCSRRD_H : IOCSRRD<0x06480400>; 2219def IOCSRRD_W : IOCSRRD<0x06480800>; 2220def IOCSRWR_B : IOCSRWR<0x06481000>; 2221def IOCSRWR_H : IOCSRWR<0x06481400>; 2222def IOCSRWR_W : IOCSRWR<0x06481800>; 2223let Predicates = [IsLA64] in { 2224def IOCSRRD_D : IOCSRRD<0x06480c00>; 2225def IOCSRWR_D : IOCSRWR<0x06481c00>; 2226} // Predicates = [IsLA64] 2227 2228// TLB Maintenance Instructions 2229let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in { 2230def TLBSRCH : FmtI32<0x06482800>; 2231def TLBRD : FmtI32<0x06482c00>; 2232def TLBWR : FmtI32<0x06483000>; 2233def TLBFILL : FmtI32<0x06483400>; 2234def TLBCLR : FmtI32<0x06482000>; 2235def TLBFLUSH : FmtI32<0x06482400>; 2236def INVTLB : FmtINVTLB<(outs), (ins GPR:$rk, GPR:$rj, uimm5:$op), 2237 "$op, $rj, $rk">; 2238} // hasSideEffects = 1, mayLoad = 0, mayStore = 0 2239 2240// Software Page Walking Instructions 2241def LDDIR : Fmt2RI8<0x06400000, (outs GPR:$rd), 2242 (ins GPR:$rj, uimm8:$imm8), "$rd, $rj, $imm8">; 2243def LDPTE : FmtLDPTE<(outs), (ins GPR:$rj, uimm8:$seq), "$rj, $seq">; 2244 2245 2246// Other Miscellaneous Instructions 2247let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 2248def ERTN : FmtI32<0x06483800>; 2249def DBCL : MISC_I15<0x002a8000>; 2250def IDLE : MISC_I15<0x06488000>; 2251 2252//===----------------------------------------------------------------------===// 2253// Privilege Intrinsics 2254//===----------------------------------------------------------------------===// 2255 2256def : Pat<(loongarch_csrrd uimm14:$imm14), (CSRRD uimm14:$imm14)>; 2257def : Pat<(loongarch_csrwr GPR:$rd, uimm14:$imm14), 2258 (CSRWR GPR:$rd, uimm14:$imm14)>; 2259def : Pat<(loongarch_csrxchg GPR:$rd, GPR:$rj, uimm14:$imm14), 2260 (CSRXCHG GPR:$rd, GPR:$rj, uimm14:$imm14)>; 2261 2262def : Pat<(loongarch_iocsrrd_b GPR:$rj), (IOCSRRD_B GPR:$rj)>; 2263def : Pat<(loongarch_iocsrrd_h GPR:$rj), (IOCSRRD_H GPR:$rj)>; 2264def : Pat<(loongarch_iocsrrd_w GPR:$rj), (IOCSRRD_W GPR:$rj)>; 2265 2266def : Pat<(loongarch_iocsrwr_b GPR:$rd, GPR:$rj), (IOCSRWR_B GPR:$rd, GPR:$rj)>; 2267def : Pat<(loongarch_iocsrwr_h GPR:$rd, GPR:$rj), (IOCSRWR_H GPR:$rd, GPR:$rj)>; 2268def : Pat<(loongarch_iocsrwr_w GPR:$rd, GPR:$rj), (IOCSRWR_W GPR:$rd, GPR:$rj)>; 2269 2270def : Pat<(loongarch_cpucfg GPR:$rj), (CPUCFG GPR:$rj)>; 2271 2272let Predicates = [IsLA64] in { 2273def : Pat<(loongarch_iocsrrd_d GPR:$rj), (IOCSRRD_D GPR:$rj)>; 2274def : Pat<(loongarch_iocsrwr_d GPR:$rd, GPR:$rj), (IOCSRWR_D GPR:$rd, GPR:$rj)>; 2275def : Pat<(int_loongarch_asrtle_d GPR:$rj, GPR:$rk), 2276 (ASRTLE_D GPR:$rj, GPR:$rk)>; 2277def : Pat<(int_loongarch_asrtgt_d GPR:$rj, GPR:$rk), 2278 (ASRTGT_D GPR:$rj, GPR:$rk)>; 2279def : Pat<(int_loongarch_lddir_d GPR:$rj, timm:$imm8), 2280 (LDDIR GPR:$rj, timm:$imm8)>; 2281def : Pat<(int_loongarch_ldpte_d GPR:$rj, timm:$imm8), 2282 (LDPTE GPR:$rj, timm:$imm8)>; 2283} // Predicates = [IsLA64] 2284 2285//===----------------------------------------------------------------------===// 2286// LSX Instructions 2287//===----------------------------------------------------------------------===// 2288include "LoongArchLSXInstrInfo.td" 2289 2290//===----------------------------------------------------------------------===// 2291// LASX Instructions 2292//===----------------------------------------------------------------------===// 2293include "LoongArchLASXInstrInfo.td" 2294 2295//===----------------------------------------------------------------------===// 2296// LVZ Instructions 2297//===----------------------------------------------------------------------===// 2298include "LoongArchLVZInstrInfo.td" 2299 2300//===----------------------------------------------------------------------===// 2301// LBT Instructions 2302//===----------------------------------------------------------------------===// 2303include "LoongArchLBTInstrInfo.td" 2304