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">; 701 702let hasSideEffects = 0, mayLoad = 0, mayStore = 1, Constraints = "$rd = $dst" in 703class SCBase<bits<32> op> 704 : Fmt2RI14<op, (outs GPR:$dst), (ins GPR:$rd, GPR:$rj, simm14_lsl2:$imm14), 705 "$rd, $rj, $imm14">; 706 707let hasSideEffects = 1 in 708class IOCSRRD<bits<32> op> 709 : Fmt2R<op, (outs GPR:$rd), (ins GPR:$rj), "$rd, $rj">; 710 711let hasSideEffects = 1 in 712class IOCSRWR<bits<32> op> 713 : Fmt2R<op, (outs), (ins GPR:$rd, GPR:$rj), "$rd, $rj">; 714 715//===----------------------------------------------------------------------===// 716// Basic Integer Instructions 717//===----------------------------------------------------------------------===// 718 719// Arithmetic Operation Instructions 720def ADD_W : ALU_3R<0x00100000>; 721def SUB_W : ALU_3R<0x00110000>; 722def ADDI_W : ALU_2RI12<0x02800000, simm12_addlike>; 723def ALSL_W : ALU_3RI2<0x00040000, uimm2_plus1>; 724def LU12I_W : ALU_1RI20<0x14000000, simm20_lu12iw>; 725def SLT : ALU_3R<0x00120000>; 726def SLTU : ALU_3R<0x00128000>; 727def SLTI : ALU_2RI12<0x02000000, simm12>; 728def SLTUI : ALU_2RI12<0x02400000, simm12>; 729def PCADDI : ALU_1RI20<0x18000000, simm20>; 730def PCADDU12I : ALU_1RI20<0x1c000000, simm20>; 731def PCALAU12I : ALU_1RI20<0x1a000000, simm20_pcalau12i>; 732def AND : ALU_3R<0x00148000>; 733def OR : ALU_3R<0x00150000>; 734def NOR : ALU_3R<0x00140000>; 735def XOR : ALU_3R<0x00158000>; 736def ANDN : ALU_3R<0x00168000>; 737def ORN : ALU_3R<0x00160000>; 738def ANDI : ALU_2RI12<0x03400000, uimm12>; 739def ORI : ALU_2RI12<0x03800000, uimm12_ori>; 740def XORI : ALU_2RI12<0x03c00000, uimm12>; 741def MUL_W : ALU_3R<0x001c0000>; 742def MULH_W : ALU_3R<0x001c8000>; 743def MULH_WU : ALU_3R<0x001d0000>; 744let usesCustomInserter = true in { 745def DIV_W : ALU_3R<0x00200000>; 746def MOD_W : ALU_3R<0x00208000>; 747def DIV_WU : ALU_3R<0x00210000>; 748def MOD_WU : ALU_3R<0x00218000>; 749} // usesCustomInserter = true 750 751// Bit-shift Instructions 752def SLL_W : ALU_3R<0x00170000>; 753def SRL_W : ALU_3R<0x00178000>; 754def SRA_W : ALU_3R<0x00180000>; 755def ROTR_W : ALU_3R<0x001b0000>; 756 757def SLLI_W : ALU_2RI5<0x00408000, uimm5>; 758def SRLI_W : ALU_2RI5<0x00448000, uimm5>; 759def SRAI_W : ALU_2RI5<0x00488000, uimm5>; 760def ROTRI_W : ALU_2RI5<0x004c8000, uimm5>; 761 762// Bit-manipulation Instructions 763def EXT_W_B : ALU_2R<0x00005c00>; 764def EXT_W_H : ALU_2R<0x00005800>; 765def CLO_W : ALU_2R<0x00001000>; 766def CLZ_W : ALU_2R<0x00001400>; 767def CTO_W : ALU_2R<0x00001800>; 768def CTZ_W : ALU_2R<0x00001c00>; 769def BYTEPICK_W : ALU_3RI2<0x00080000, uimm2>; 770def REVB_2H : ALU_2R<0x00003000>; 771def BITREV_4B : ALU_2R<0x00004800>; 772def BITREV_W : ALU_2R<0x00005000>; 773let Constraints = "$rd = $dst" in { 774def BSTRINS_W : FmtBSTR_W<0x00600000, (outs GPR:$dst), 775 (ins GPR:$rd, GPR:$rj, uimm5:$msbw, uimm5:$lsbw), 776 "$rd, $rj, $msbw, $lsbw">; 777} 778def BSTRPICK_W : FmtBSTR_W<0x00608000, (outs GPR:$rd), 779 (ins GPR:$rj, uimm5:$msbw, uimm5:$lsbw), 780 "$rd, $rj, $msbw, $lsbw">; 781def MASKEQZ : ALU_3R<0x00130000>; 782def MASKNEZ : ALU_3R<0x00138000>; 783 784// Branch Instructions 785def BEQ : BrCC_2RI16<0x58000000>; 786def BNE : BrCC_2RI16<0x5c000000>; 787def BLT : BrCC_2RI16<0x60000000>; 788def BGE : BrCC_2RI16<0x64000000>; 789def BLTU : BrCC_2RI16<0x68000000>; 790def BGEU : BrCC_2RI16<0x6c000000>; 791def BEQZ : BrCCZ_1RI21<0x40000000>; 792def BNEZ : BrCCZ_1RI21<0x44000000>; 793def B : Br_I26<0x50000000>; 794 795let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCall = 1, Defs=[R1] in 796def BL : FmtI26<0x54000000, (outs), (ins simm26_symbol:$imm26), "$imm26">; 797let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 798def JIRL : Fmt2RI16<0x4c000000, (outs GPR:$rd), 799 (ins GPR:$rj, simm16_lsl2:$imm16), "$rd, $rj, $imm16">; 800 801// Common Memory Access Instructions 802def LD_B : LOAD_2RI12<0x28000000>; 803def LD_H : LOAD_2RI12<0x28400000>; 804def LD_W : LOAD_2RI12<0x28800000>; 805def LD_BU : LOAD_2RI12<0x2a000000>; 806def LD_HU : LOAD_2RI12<0x2a400000>; 807def ST_B : STORE_2RI12<0x29000000>; 808def ST_H : STORE_2RI12<0x29400000>; 809def ST_W : STORE_2RI12<0x29800000>; 810let hasSideEffects = 0, mayLoad = 1, mayStore = 1 in 811def PRELD : FmtPRELD<(outs), (ins uimm5:$imm5, GPR:$rj, simm12:$imm12), 812 "$imm5, $rj, $imm12">; 813 814// Atomic Memory Access Instructions 815def LL_W : LLBase<0x20000000>; 816def SC_W : SCBase<0x21000000>; 817 818// Barrier Instructions 819def DBAR : MISC_I15<0x38720000>; 820def IBAR : MISC_I15<0x38728000>; 821 822// Other Miscellaneous Instructions 823def SYSCALL : MISC_I15<0x002b0000>; 824def BREAK : MISC_I15<0x002a0000>; 825def RDTIMEL_W : RDTIME_2R<0x00006000>; 826def RDTIMEH_W : RDTIME_2R<0x00006400>; 827def CPUCFG : ALU_2R<0x00006c00>; 828 829// Cache Maintenance Instructions 830def CACOP : FmtCACOP<(outs), (ins uimm5:$op, GPR:$rj, simm12:$imm12), 831 "$op, $rj, $imm12">; 832 833/// LA64 instructions 834 835let Predicates = [IsLA64] in { 836 837// Arithmetic Operation Instructions for 64-bits 838def ADD_D : ALU_3R<0x00108000>; 839def SUB_D : ALU_3R<0x00118000>; 840def ADDI_D : ALU_2RI12<0x02c00000, simm12_addlike>; 841def ADDU16I_D : ALU_2RI16<0x10000000, simm16>; 842def ALSL_WU : ALU_3RI2<0x00060000, uimm2_plus1>; 843def ALSL_D : ALU_3RI2<0x002c0000, uimm2_plus1>; 844let Constraints = "$rd = $dst" in { 845let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 846def LU32I_D : Fmt1RI20<0x16000000, (outs GPR:$dst), 847 (ins GPR:$rd, simm20_lu32id:$imm20), 848 "$rd, $imm20">; 849} 850def LU52I_D : ALU_2RI12<0x03000000, simm12_lu52id>; 851def PCADDU18I : ALU_1RI20<0x1e000000, simm20_pcaddu18i>; 852def MUL_D : ALU_3R<0x001d8000>; 853def MULH_D : ALU_3R<0x001e0000>; 854def MULH_DU : ALU_3R<0x001e8000>; 855def MULW_D_W : ALU_3R<0x001f0000>; 856def MULW_D_WU : ALU_3R<0x001f8000>; 857let usesCustomInserter = true in { 858def DIV_D : ALU_3R<0x00220000>; 859def MOD_D : ALU_3R<0x00228000>; 860def DIV_DU : ALU_3R<0x00230000>; 861def MOD_DU : ALU_3R<0x00238000>; 862} // usesCustomInserter = true 863 864// Bit-shift Instructions for 64-bits 865def SLL_D : ALU_3R<0x00188000>; 866def SRL_D : ALU_3R<0x00190000>; 867def SRA_D : ALU_3R<0x00198000>; 868def ROTR_D : ALU_3R<0x001b8000>; 869def SLLI_D : ALU_2RI6<0x00410000, uimm6>; 870def SRLI_D : ALU_2RI6<0x00450000, uimm6>; 871def SRAI_D : ALU_2RI6<0x00490000, uimm6>; 872def ROTRI_D : ALU_2RI6<0x004d0000, uimm6>; 873 874// Bit-manipulation Instructions for 64-bits 875def CLO_D : ALU_2R<0x00002000>; 876def CLZ_D : ALU_2R<0x00002400>; 877def CTO_D : ALU_2R<0x00002800>; 878def CTZ_D : ALU_2R<0x00002c00>; 879def BYTEPICK_D : ALU_3RI3<0x000c0000, uimm3>; 880def REVB_4H : ALU_2R<0x00003400>; 881def REVB_2W : ALU_2R<0x00003800>; 882def REVB_D : ALU_2R<0x00003c00>; 883def REVH_2W : ALU_2R<0x00004000>; 884def REVH_D : ALU_2R<0x00004400>; 885def BITREV_8B : ALU_2R<0x00004c00>; 886def BITREV_D : ALU_2R<0x00005400>; 887let Constraints = "$rd = $dst" in { 888def BSTRINS_D : FmtBSTR_D<0x00800000, (outs GPR:$dst), 889 (ins GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd), 890 "$rd, $rj, $msbd, $lsbd">; 891} 892def BSTRPICK_D : FmtBSTR_D<0x00c00000, (outs GPR:$rd), 893 (ins GPR:$rj, uimm6:$msbd, uimm6:$lsbd), 894 "$rd, $rj, $msbd, $lsbd">; 895 896// Common Memory Access Instructions for 64-bits 897def LD_WU : LOAD_2RI12<0x2a800000>; 898def LD_D : LOAD_2RI12<0x28c00000>; 899def ST_D : STORE_2RI12<0x29c00000>; 900def LDX_B : LOAD_3R<0x38000000>; 901def LDX_H : LOAD_3R<0x38040000>; 902def LDX_W : LOAD_3R<0x38080000>; 903def LDX_D : LOAD_3R<0x380c0000>; 904def LDX_BU : LOAD_3R<0x38200000>; 905def LDX_HU : LOAD_3R<0x38240000>; 906def LDX_WU : LOAD_3R<0x38280000>; 907def STX_B : STORE_3R<0x38100000>; 908def STX_H : STORE_3R<0x38140000>; 909def STX_W : STORE_3R<0x38180000>; 910def STX_D : STORE_3R<0x381c0000>; 911def LDPTR_W : LOAD_2RI14<0x24000000>; 912def LDPTR_D : LOAD_2RI14<0x26000000>; 913def STPTR_W : STORE_2RI14<0x25000000>; 914def STPTR_D : STORE_2RI14<0x27000000>; 915let hasSideEffects = 0, mayLoad = 1, mayStore = 1 in 916def PRELDX : FmtPRELDX<(outs), (ins uimm5:$imm5, GPR:$rj, GPR:$rk), 917 "$imm5, $rj, $rk">; 918 919// Bound Check Memory Access Instructions 920def LDGT_B : LOAD_3R<0x38780000>; 921def LDGT_H : LOAD_3R<0x38788000>; 922def LDGT_W : LOAD_3R<0x38790000>; 923def LDGT_D : LOAD_3R<0x38798000>; 924def LDLE_B : LOAD_3R<0x387a0000>; 925def LDLE_H : LOAD_3R<0x387a8000>; 926def LDLE_W : LOAD_3R<0x387b0000>; 927def LDLE_D : LOAD_3R<0x387b8000>; 928def STGT_B : STORE_3R<0x387c0000>; 929def STGT_H : STORE_3R<0x387c8000>; 930def STGT_W : STORE_3R<0x387d0000>; 931def STGT_D : STORE_3R<0x387d8000>; 932def STLE_B : STORE_3R<0x387e0000>; 933def STLE_H : STORE_3R<0x387e8000>; 934def STLE_W : STORE_3R<0x387f0000>; 935def STLE_D : STORE_3R<0x387f8000>; 936 937// Atomic Memory Access Instructions for 64-bits 938def AMSWAP_W : AM_3R<0x38600000>; 939def AMSWAP_D : AM_3R<0x38608000>; 940def AMADD_W : AM_3R<0x38610000>; 941def AMADD_D : AM_3R<0x38618000>; 942def AMAND_W : AM_3R<0x38620000>; 943def AMAND_D : AM_3R<0x38628000>; 944def AMOR_W : AM_3R<0x38630000>; 945def AMOR_D : AM_3R<0x38638000>; 946def AMXOR_W : AM_3R<0x38640000>; 947def AMXOR_D : AM_3R<0x38648000>; 948def AMMAX_W : AM_3R<0x38650000>; 949def AMMAX_D : AM_3R<0x38658000>; 950def AMMIN_W : AM_3R<0x38660000>; 951def AMMIN_D : AM_3R<0x38668000>; 952def AMMAX_WU : AM_3R<0x38670000>; 953def AMMAX_DU : AM_3R<0x38678000>; 954def AMMIN_WU : AM_3R<0x38680000>; 955def AMMIN_DU : AM_3R<0x38688000>; 956def AMSWAP__DB_W : AM_3R<0x38690000>; 957def AMSWAP__DB_D : AM_3R<0x38698000>; 958def AMADD__DB_W : AM_3R<0x386a0000>; 959def AMADD__DB_D : AM_3R<0x386a8000>; 960def AMAND__DB_W : AM_3R<0x386b0000>; 961def AMAND__DB_D : AM_3R<0x386b8000>; 962def AMOR__DB_W : AM_3R<0x386c0000>; 963def AMOR__DB_D : AM_3R<0x386c8000>; 964def AMXOR__DB_W : AM_3R<0x386d0000>; 965def AMXOR__DB_D : AM_3R<0x386d8000>; 966def AMMAX__DB_W : AM_3R<0x386e0000>; 967def AMMAX__DB_D : AM_3R<0x386e8000>; 968def AMMIN__DB_W : AM_3R<0x386f0000>; 969def AMMIN__DB_D : AM_3R<0x386f8000>; 970def AMMAX__DB_WU : AM_3R<0x38700000>; 971def AMMAX__DB_DU : AM_3R<0x38708000>; 972def AMMIN__DB_WU : AM_3R<0x38710000>; 973def AMMIN__DB_DU : AM_3R<0x38718000>; 974def LL_D : LLBase<0x22000000>; 975def SC_D : SCBase<0x23000000>; 976 977// CRC Check Instructions 978def CRC_W_B_W : ALU_3R<0x00240000>; 979def CRC_W_H_W : ALU_3R<0x00248000>; 980def CRC_W_W_W : ALU_3R<0x00250000>; 981def CRC_W_D_W : ALU_3R<0x00258000>; 982def CRCC_W_B_W : ALU_3R<0x00260000>; 983def CRCC_W_H_W : ALU_3R<0x00268000>; 984def CRCC_W_W_W : ALU_3R<0x00270000>; 985def CRCC_W_D_W : ALU_3R<0x00278000>; 986 987// Other Miscellaneous Instructions for 64-bits 988def ASRTLE_D : FmtASRT<0x00010000, (outs), (ins GPR:$rj, GPR:$rk), 989 "$rj, $rk">; 990def ASRTGT_D : FmtASRT<0x00018000, (outs), (ins GPR:$rj, GPR:$rk), 991 "$rj, $rk">; 992def RDTIME_D : RDTIME_2R<0x00006800>; 993} // Predicates = [IsLA64] 994 995//===----------------------------------------------------------------------===// 996// Pseudo-instructions and codegen patterns 997// 998// Naming convention: For 'generic' pattern classes, we use the naming 999// convention PatTy1Ty2. 1000//===----------------------------------------------------------------------===// 1001 1002/// Generic pattern classes 1003 1004class PatGprGpr<SDPatternOperator OpNode, LAInst Inst> 1005 : Pat<(OpNode GPR:$rj, GPR:$rk), (Inst GPR:$rj, GPR:$rk)>; 1006class PatGprGpr_32<SDPatternOperator OpNode, LAInst Inst> 1007 : Pat<(sext_inreg (OpNode GPR:$rj, GPR:$rk), i32), (Inst GPR:$rj, GPR:$rk)>; 1008class PatGpr<SDPatternOperator OpNode, LAInst Inst> 1009 : Pat<(OpNode GPR:$rj), (Inst GPR:$rj)>; 1010 1011class PatGprImm<SDPatternOperator OpNode, LAInst Inst, Operand ImmOpnd> 1012 : Pat<(OpNode GPR:$rj, ImmOpnd:$imm), 1013 (Inst GPR:$rj, ImmOpnd:$imm)>; 1014class PatGprImm_32<SDPatternOperator OpNode, LAInst Inst, Operand ImmOpnd> 1015 : Pat<(sext_inreg (OpNode GPR:$rj, ImmOpnd:$imm), i32), 1016 (Inst GPR:$rj, ImmOpnd:$imm)>; 1017 1018/// Predicates 1019def AddLike: PatFrags<(ops node:$A, node:$B), 1020 [(add node:$A, node:$B), (or node:$A, node:$B)], [{ 1021 return N->getOpcode() == ISD::ADD || isOrEquivalentToAdd(N); 1022}]>; 1023 1024/// Simple arithmetic operations 1025 1026// Match both a plain shift and one where the shift amount is masked (this is 1027// typically introduced when the legalizer promotes the shift amount and 1028// zero-extends it). For LoongArch, the mask is unnecessary as shifts in the 1029// base ISA only read the least significant 5 bits (LA32) or 6 bits (LA64). 1030def shiftMaskGRLen 1031 : ComplexPattern<GRLenVT, 1, "selectShiftMaskGRLen", [], [], 0>; 1032def shiftMask32 : ComplexPattern<i64, 1, "selectShiftMask32", [], [], 0>; 1033 1034def sexti32 : ComplexPattern<i64, 1, "selectSExti32">; 1035def zexti32 : ComplexPattern<i64, 1, "selectZExti32">; 1036 1037class shiftop<SDPatternOperator operator> 1038 : PatFrag<(ops node:$val, node:$count), 1039 (operator node:$val, (GRLenVT (shiftMaskGRLen node:$count)))>; 1040class shiftopw<SDPatternOperator operator> 1041 : PatFrag<(ops node:$val, node:$count), 1042 (operator node:$val, (i64 (shiftMask32 node:$count)))>; 1043 1044def mul_const_oneuse : PatFrag<(ops node:$A, node:$B), 1045 (mul node:$A, node:$B), [{ 1046 if (auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1))) 1047 return N1C->hasOneUse(); 1048 return false; 1049}]>; 1050 1051let Predicates = [IsLA32] in { 1052def : PatGprGpr<add, ADD_W>; 1053def : PatGprImm<add, ADDI_W, simm12>; 1054def : PatGprGpr<sub, SUB_W>; 1055def : PatGprGpr<sdiv, DIV_W>; 1056def : PatGprGpr<udiv, DIV_WU>; 1057def : PatGprGpr<srem, MOD_W>; 1058def : PatGprGpr<urem, MOD_WU>; 1059def : PatGprGpr<mul, MUL_W>; 1060def : PatGprGpr<mulhs, MULH_W>; 1061def : PatGprGpr<mulhu, MULH_WU>; 1062def : PatGprGpr<rotr, ROTR_W>; 1063def : PatGprImm<rotr, ROTRI_W, uimm5>; 1064 1065foreach Idx = 1...3 in { 1066 defvar ShamtA = !mul(8, Idx); 1067 defvar ShamtB = !mul(8, !sub(4, Idx)); 1068 def : Pat<(or (shl GPR:$rk, (i32 ShamtA)), (srl GPR:$rj, (i32 ShamtB))), 1069 (BYTEPICK_W GPR:$rj, GPR:$rk, Idx)>; 1070} 1071} // Predicates = [IsLA32] 1072 1073let Predicates = [IsLA64] in { 1074def : PatGprGpr<add, ADD_D>; 1075def : PatGprGpr_32<add, ADD_W>; 1076def : PatGprImm<add, ADDI_D, simm12>; 1077def : PatGprImm_32<add, ADDI_W, simm12>; 1078def : PatGprGpr<sub, SUB_D>; 1079def : PatGprGpr_32<sub, SUB_W>; 1080def : PatGprGpr<sdiv, DIV_D>; 1081def : PatGprGpr<udiv, DIV_DU>; 1082def : PatGprGpr<srem, MOD_D>; 1083def : PatGprGpr<urem, MOD_DU>; 1084def : PatGprGpr<rotr, ROTR_D>; 1085def : PatGprGpr<loongarch_rotr_w, ROTR_W>; 1086def : PatGprImm<rotr, ROTRI_D, uimm6>; 1087def : PatGprImm_32<rotr, ROTRI_W, uimm5>; 1088def : Pat<(loongarch_rotl_w GPR:$rj, uimm5:$imm), 1089 (ROTRI_W GPR:$rj, (ImmSubFrom32 uimm5:$imm))>; 1090def : Pat<(sext_inreg (loongarch_rotl_w GPR:$rj, uimm5:$imm), i32), 1091 (ROTRI_W GPR:$rj, (ImmSubFrom32 uimm5:$imm))>; 1092// TODO: Select "_W[U]" instructions for i32xi32 if only lower 32 bits of the 1093// product are used. 1094def : PatGprGpr<mul, MUL_D>; 1095def : PatGprGpr<mulhs, MULH_D>; 1096def : PatGprGpr<mulhu, MULH_DU>; 1097// Select MULW_D_W for calculating the full 64 bits product of i32xi32 signed 1098// multiplication. 1099def : Pat<(i64 (mul (sext_inreg GPR:$rj, i32), (sext_inreg GPR:$rk, i32))), 1100 (MULW_D_W GPR:$rj, GPR:$rk)>; 1101// Select MULW_D_WU for calculating the full 64 bits product of i32xi32 1102// unsigned multiplication. 1103def : Pat<(i64 (mul (loongarch_bstrpick GPR:$rj, (i64 31), (i64 0)), 1104 (loongarch_bstrpick GPR:$rk, (i64 31), (i64 0)))), 1105 (MULW_D_WU GPR:$rj, GPR:$rk)>; 1106 1107def : Pat<(add GPR:$rj, simm16_lsl16:$imm), 1108 (ADDU16I_D GPR:$rj, (HI16 $imm))>; 1109def : Pat<(add GPR:$rj, simm32_hi16_lo12:$imm), 1110 (ADDI_D (ADDU16I_D GPR:$rj, (HI16ForAddu16idAddiPair $imm)), 1111 (LO12 $imm))>; 1112def : Pat<(sext_inreg (add GPR:$rj, simm32_hi16_lo12:$imm), i32), 1113 (ADDI_W (ADDU16I_D GPR:$rj, (HI16ForAddu16idAddiPair $imm)), 1114 (LO12 $imm))>; 1115 1116let Predicates = [IsLA32] in { 1117def : Pat<(add GPR:$rj, (AddiPair:$im)), 1118 (ADDI_W (ADDI_W GPR:$rj, (AddiPairImmLarge AddiPair:$im)), 1119 (AddiPairImmSmall AddiPair:$im))>; 1120} // Predicates = [IsLA32] 1121 1122let Predicates = [IsLA64] in { 1123def : Pat<(add GPR:$rj, (AddiPair:$im)), 1124 (ADDI_D (ADDI_D GPR:$rj, (AddiPairImmLarge AddiPair:$im)), 1125 (AddiPairImmSmall AddiPair:$im))>; 1126def : Pat<(sext_inreg (add GPR:$rj, (AddiPair:$im)), i32), 1127 (ADDI_W (ADDI_W GPR:$rj, (AddiPairImmLarge AddiPair:$im)), 1128 (AddiPairImmSmall AddiPair:$im))>; 1129} // Predicates = [IsLA64] 1130 1131let Predicates = [IsLA32] in { 1132foreach Idx0 = 1...4 in { 1133 foreach Idx1 = 1...4 in { 1134 defvar CImm = !add(1, !shl(!add(1, !shl(1, Idx0)), Idx1)); 1135 def : Pat<(mul_const_oneuse GPR:$r, (i32 CImm)), 1136 (ALSL_W (ALSL_W GPR:$r, GPR:$r, (i32 Idx0)), 1137 GPR:$r, (i32 Idx1))>; 1138 } 1139} 1140foreach Idx0 = 1...4 in { 1141 foreach Idx1 = 1...4 in { 1142 defvar Cb = !add(1, !shl(1, Idx0)); 1143 defvar CImm = !add(Cb, !shl(Cb, Idx1)); 1144 def : Pat<(mul_const_oneuse GPR:$r, (i32 CImm)), 1145 (ALSL_W (ALSL_W GPR:$r, GPR:$r, (i32 Idx0)), 1146 (ALSL_W GPR:$r, GPR:$r, (i32 Idx0)), (i32 Idx1))>; 1147 } 1148} 1149} // Predicates = [IsLA32] 1150 1151let Predicates = [IsLA64] in { 1152foreach Idx0 = 1...4 in { 1153 foreach Idx1 = 1...4 in { 1154 defvar CImm = !add(1, !shl(!add(1, !shl(1, Idx0)), Idx1)); 1155 def : Pat<(sext_inreg (mul_const_oneuse GPR:$r, (i64 CImm)), i32), 1156 (ALSL_W (ALSL_W GPR:$r, GPR:$r, (i64 Idx0)), 1157 GPR:$r, (i64 Idx1))>; 1158 def : Pat<(mul_const_oneuse GPR:$r, (i64 CImm)), 1159 (ALSL_D (ALSL_D GPR:$r, GPR:$r, (i64 Idx0)), 1160 GPR:$r, (i64 Idx1))>; 1161 } 1162} 1163foreach Idx0 = 1...4 in { 1164 foreach Idx1 = 1...4 in { 1165 defvar Cb = !add(1, !shl(1, Idx0)); 1166 defvar CImm = !add(Cb, !shl(Cb, Idx1)); 1167 def : Pat<(sext_inreg (mul_const_oneuse GPR:$r, (i64 CImm)), i32), 1168 (ALSL_W (ALSL_W GPR:$r, GPR:$r, (i64 Idx0)), 1169 (ALSL_W GPR:$r, GPR:$r, (i64 Idx0)), (i64 Idx1))>; 1170 def : Pat<(mul_const_oneuse GPR:$r, (i64 CImm)), 1171 (ALSL_D (ALSL_D GPR:$r, GPR:$r, (i64 Idx0)), 1172 (ALSL_D GPR:$r, GPR:$r, (i64 Idx0)), (i64 Idx1))>; 1173 } 1174} 1175} // Predicates = [IsLA64] 1176 1177let Predicates = [IsLA32] in { 1178def : Pat<(mul GPR:$rj, (AlslSlliImm:$im)), 1179 (SLLI_W (ALSL_W GPR:$rj, GPR:$rj, (AlslSlliImmI0 AlslSlliImm:$im)), 1180 (AlslSlliImmI1 AlslSlliImm:$im))>; 1181} // Predicates = [IsLA32] 1182 1183let Predicates = [IsLA64] in { 1184def : Pat<(sext_inreg (mul GPR:$rj, (AlslSlliImm:$im)), i32), 1185 (SLLI_W (ALSL_W GPR:$rj, GPR:$rj, (AlslSlliImmI0 AlslSlliImm:$im)), 1186 (AlslSlliImmI1 AlslSlliImm:$im))>; 1187def : Pat<(mul GPR:$rj, (AlslSlliImm:$im)), 1188 (SLLI_D (ALSL_D GPR:$rj, GPR:$rj, (AlslSlliImmI0 AlslSlliImm:$im)), 1189 (AlslSlliImmI1 AlslSlliImm:$im))>; 1190} // Predicates = [IsLA64] 1191 1192foreach Idx = 1...7 in { 1193 defvar ShamtA = !mul(8, Idx); 1194 defvar ShamtB = !mul(8, !sub(8, Idx)); 1195 def : Pat<(or (shl GPR:$rk, (i64 ShamtA)), (srl GPR:$rj, (i64 ShamtB))), 1196 (BYTEPICK_D GPR:$rj, GPR:$rk, Idx)>; 1197} 1198 1199foreach Idx = 1...3 in { 1200 defvar ShamtA = !mul(8, Idx); 1201 defvar ShamtB = !mul(8, !sub(4, Idx)); 1202 // NOTE: the srl node would already be transformed into a loongarch_bstrpick 1203 // by the time this pattern gets to execute, hence the weird construction. 1204 def : Pat<(sext_inreg (or (shl GPR:$rk, (i64 ShamtA)), 1205 (loongarch_bstrpick GPR:$rj, (i64 31), 1206 (i64 ShamtB))), i32), 1207 (BYTEPICK_W GPR:$rj, GPR:$rk, Idx)>; 1208} 1209} // Predicates = [IsLA64] 1210 1211def : PatGprGpr<and, AND>; 1212def : PatGprImm<and, ANDI, uimm12>; 1213def : PatGprGpr<or, OR>; 1214def : PatGprImm<or, ORI, uimm12>; 1215def : PatGprGpr<xor, XOR>; 1216def : PatGprImm<xor, XORI, uimm12>; 1217def : Pat<(not GPR:$rj), (NOR GPR:$rj, R0)>; 1218def : Pat<(not (or GPR:$rj, GPR:$rk)), (NOR GPR:$rj, GPR:$rk)>; 1219def : Pat<(or GPR:$rj, (not GPR:$rk)), (ORN GPR:$rj, GPR:$rk)>; 1220def : Pat<(and GPR:$rj, (not GPR:$rk)), (ANDN GPR:$rj, GPR:$rk)>; 1221 1222let Predicates = [IsLA32] in { 1223def : Pat<(and GPR:$rj, BstrinsImm:$imm), 1224 (BSTRINS_W GPR:$rj, R0, (BstrinsMsb BstrinsImm:$imm), 1225 (BstrinsLsb BstrinsImm:$imm))>; 1226} // Predicates = [IsLA32] 1227 1228let Predicates = [IsLA64] in { 1229def : Pat<(and GPR:$rj, BstrinsImm:$imm), 1230 (BSTRINS_D GPR:$rj, R0, (BstrinsMsb BstrinsImm:$imm), 1231 (BstrinsLsb BstrinsImm:$imm))>; 1232} // Predicates = [IsLA64] 1233 1234/// Traps 1235 1236// We lower `trap` to `amswap.w rd:$r0, rk:$r1, rj:$r0`, as this is guaranteed 1237// to trap with an INE (non-existent on LA32, explicitly documented to INE on 1238// LA64). And the resulting signal is different from `debugtrap` like on some 1239// other existing ports so programs/porters might have an easier time. 1240def PseudoUNIMP : Pseudo<(outs), (ins), [(trap)]>, 1241 PseudoInstExpansion<(AMSWAP_W R0, R1, R0)>; 1242 1243// We lower `debugtrap` to `break 0`, as this is guaranteed to exist and work, 1244// even for LA32 Primary. Also, because so far the ISA does not provide a 1245// specific trap instruction/kind exclusively for alerting the debugger, 1246// every other project uses the generic immediate of 0 for this. 1247def : Pat<(debugtrap), (BREAK 0)>; 1248 1249/// Bit counting operations 1250 1251let Predicates = [IsLA64] in { 1252def : PatGpr<ctlz, CLZ_D>; 1253def : PatGpr<cttz, CTZ_D>; 1254def : Pat<(ctlz (not GPR:$rj)), (CLO_D GPR:$rj)>; 1255def : Pat<(cttz (not GPR:$rj)), (CTO_D GPR:$rj)>; 1256def : PatGpr<loongarch_clzw, CLZ_W>; 1257def : PatGpr<loongarch_ctzw, CTZ_W>; 1258def : Pat<(loongarch_clzw (not GPR:$rj)), (CLO_W GPR:$rj)>; 1259def : Pat<(loongarch_ctzw (not GPR:$rj)), (CTO_W GPR:$rj)>; 1260} // Predicates = [IsLA64] 1261 1262let Predicates = [IsLA32] in { 1263def : PatGpr<ctlz, CLZ_W>; 1264def : PatGpr<cttz, CTZ_W>; 1265def : Pat<(ctlz (not GPR:$rj)), (CLO_W GPR:$rj)>; 1266def : Pat<(cttz (not GPR:$rj)), (CTO_W GPR:$rj)>; 1267} // Predicates = [IsLA32] 1268 1269/// FrameIndex calculations 1270let Predicates = [IsLA32] in { 1271def : Pat<(AddLike (i32 BaseAddr:$rj), simm12:$imm12), 1272 (ADDI_W (i32 BaseAddr:$rj), simm12:$imm12)>; 1273} // Predicates = [IsLA32] 1274let Predicates = [IsLA64] in { 1275def : Pat<(AddLike (i64 BaseAddr:$rj), simm12:$imm12), 1276 (ADDI_D (i64 BaseAddr:$rj), simm12:$imm12)>; 1277} // Predicates = [IsLA64] 1278 1279/// Shifted addition 1280let Predicates = [IsLA32] in { 1281def : Pat<(add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)), 1282 (ALSL_W GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>; 1283} // Predicates = [IsLA32] 1284let Predicates = [IsLA64] in { 1285def : Pat<(add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)), 1286 (ALSL_D GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>; 1287def : Pat<(sext_inreg (add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)), i32), 1288 (ALSL_W GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>; 1289def : Pat<(loongarch_bstrpick (add GPR:$rk, (shl GPR:$rj, uimm2_plus1:$imm2)), 1290 (i64 31), (i64 0)), 1291 (ALSL_WU GPR:$rj, GPR:$rk, uimm2_plus1:$imm2)>; 1292} // Predicates = [IsLA64] 1293 1294/// Shift 1295 1296let Predicates = [IsLA32] in { 1297def : PatGprGpr<shiftop<shl>, SLL_W>; 1298def : PatGprGpr<shiftop<sra>, SRA_W>; 1299def : PatGprGpr<shiftop<srl>, SRL_W>; 1300def : PatGprImm<shl, SLLI_W, uimm5>; 1301def : PatGprImm<sra, SRAI_W, uimm5>; 1302def : PatGprImm<srl, SRLI_W, uimm5>; 1303} // Predicates = [IsLA32] 1304 1305let Predicates = [IsLA64] in { 1306def : PatGprGpr<shiftopw<loongarch_sll_w>, SLL_W>; 1307def : PatGprGpr<shiftopw<loongarch_sra_w>, SRA_W>; 1308def : PatGprGpr<shiftopw<loongarch_srl_w>, SRL_W>; 1309def : PatGprGpr<shiftop<shl>, SLL_D>; 1310def : PatGprGpr<shiftop<sra>, SRA_D>; 1311def : PatGprGpr<shiftop<srl>, SRL_D>; 1312def : PatGprImm<shl, SLLI_D, uimm6>; 1313def : PatGprImm<sra, SRAI_D, uimm6>; 1314def : PatGprImm<srl, SRLI_D, uimm6>; 1315} // Predicates = [IsLA64] 1316 1317/// sext and zext 1318 1319def : Pat<(sext_inreg GPR:$rj, i8), (EXT_W_B GPR:$rj)>; 1320def : Pat<(sext_inreg GPR:$rj, i16), (EXT_W_H GPR:$rj)>; 1321 1322let Predicates = [IsLA64] in { 1323def : Pat<(sext_inreg GPR:$rj, i32), (ADDI_W GPR:$rj, 0)>; 1324} // Predicates = [IsLA64] 1325 1326/// Setcc 1327 1328def : PatGprGpr<setlt, SLT>; 1329def : PatGprImm<setlt, SLTI, simm12>; 1330def : PatGprGpr<setult, SLTU>; 1331def : PatGprImm<setult, SLTUI, simm12>; 1332 1333// Define pattern expansions for setcc operations that aren't directly 1334// handled by a LoongArch instruction. 1335def : Pat<(seteq GPR:$rj, 0), (SLTUI GPR:$rj, 1)>; 1336def : Pat<(seteq GPR:$rj, GPR:$rk), (SLTUI (XOR GPR:$rj, GPR:$rk), 1)>; 1337let Predicates = [IsLA32] in { 1338def : Pat<(seteq GPR:$rj, simm12_plus1:$imm12), 1339 (SLTUI (ADDI_W GPR:$rj, (NegImm simm12_plus1:$imm12)), 1)>; 1340} // Predicates = [IsLA32] 1341let Predicates = [IsLA64] in { 1342def : Pat<(seteq GPR:$rj, simm12_plus1:$imm12), 1343 (SLTUI (ADDI_D GPR:$rj, (NegImm simm12_plus1:$imm12)), 1)>; 1344} // Predicates = [IsLA64] 1345def : Pat<(setne GPR:$rj, 0), (SLTU R0, GPR:$rj)>; 1346def : Pat<(setne GPR:$rj, GPR:$rk), (SLTU R0, (XOR GPR:$rj, GPR:$rk))>; 1347let Predicates = [IsLA32] in { 1348def : Pat<(setne GPR:$rj, simm12_plus1:$imm12), 1349 (SLTU R0, (ADDI_W GPR:$rj, (NegImm simm12_plus1:$imm12)))>; 1350} // Predicates = [IsLA32] 1351let Predicates = [IsLA64] in { 1352def : Pat<(setne GPR:$rj, simm12_plus1:$imm12), 1353 (SLTU R0, (ADDI_D GPR:$rj, (NegImm simm12_plus1:$imm12)))>; 1354} // Predicates = [IsLA64] 1355def : Pat<(setugt GPR:$rj, GPR:$rk), (SLTU GPR:$rk, GPR:$rj)>; 1356def : Pat<(setuge GPR:$rj, GPR:$rk), (XORI (SLTU GPR:$rj, GPR:$rk), 1)>; 1357def : Pat<(setule GPR:$rj, GPR:$rk), (XORI (SLTU GPR:$rk, GPR:$rj), 1)>; 1358def : Pat<(setgt GPR:$rj, GPR:$rk), (SLT GPR:$rk, GPR:$rj)>; 1359def : Pat<(setge GPR:$rj, GPR:$rk), (XORI (SLT GPR:$rj, GPR:$rk), 1)>; 1360def : Pat<(setle GPR:$rj, GPR:$rk), (XORI (SLT GPR:$rk, GPR:$rj), 1)>; 1361 1362/// Select 1363 1364def : Pat<(select GPR:$cond, GPR:$t, 0), (MASKEQZ GPR:$t, GPR:$cond)>; 1365def : Pat<(select GPR:$cond, 0, GPR:$f), (MASKNEZ GPR:$f, GPR:$cond)>; 1366def : Pat<(select GPR:$cond, GPR:$t, GPR:$f), 1367 (OR (MASKEQZ GPR:$t, GPR:$cond), (MASKNEZ GPR:$f, GPR:$cond))>; 1368 1369/// Branches and jumps 1370 1371class BccPat<PatFrag CondOp, LAInst Inst> 1372 : Pat<(brcond (GRLenVT (CondOp GPR:$rj, GPR:$rd)), bb:$imm16), 1373 (Inst GPR:$rj, GPR:$rd, bb:$imm16)>; 1374 1375def : BccPat<seteq, BEQ>; 1376def : BccPat<setne, BNE>; 1377def : BccPat<setlt, BLT>; 1378def : BccPat<setge, BGE>; 1379def : BccPat<setult, BLTU>; 1380def : BccPat<setuge, BGEU>; 1381 1382class BccSwapPat<PatFrag CondOp, LAInst InstBcc> 1383 : Pat<(brcond (GRLenVT (CondOp GPR:$rd, GPR:$rj)), bb:$imm16), 1384 (InstBcc GPR:$rj, GPR:$rd, bb:$imm16)>; 1385 1386// Condition codes that don't have matching LoongArch branch instructions, but 1387// are trivially supported by swapping the two input operands. 1388def : BccSwapPat<setgt, BLT>; 1389def : BccSwapPat<setle, BGE>; 1390def : BccSwapPat<setugt, BLTU>; 1391def : BccSwapPat<setule, BGEU>; 1392 1393// An extra pattern is needed for a brcond without a setcc (i.e. where the 1394// condition was calculated elsewhere). 1395def : Pat<(brcond GPR:$rj, bb:$imm21), (BNEZ GPR:$rj, bb:$imm21)>; 1396 1397def : Pat<(brcond (GRLenVT (seteq GPR:$rj, 0)), bb:$imm21), 1398 (BEQZ GPR:$rj, bb:$imm21)>; 1399def : Pat<(brcond (GRLenVT (setne GPR:$rj, 0)), bb:$imm21), 1400 (BNEZ GPR:$rj, bb:$imm21)>; 1401 1402let isBarrier = 1, isBranch = 1, isTerminator = 1 in 1403def PseudoBR : Pseudo<(outs), (ins simm26_b:$imm26), [(br bb:$imm26)]>, 1404 PseudoInstExpansion<(B simm26_b:$imm26)>; 1405 1406let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in 1407def PseudoBRIND : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>, 1408 PseudoInstExpansion<(JIRL R0, GPR:$rj, simm16_lsl2:$imm16)>; 1409 1410def : Pat<(brind GPR:$rj), (PseudoBRIND GPR:$rj, 0)>; 1411def : Pat<(brind (add GPR:$rj, simm16_lsl2:$imm16)), 1412 (PseudoBRIND GPR:$rj, simm16_lsl2:$imm16)>; 1413 1414// Function call with 'Small' code model. 1415let isCall = 1, Defs = [R1] in 1416def PseudoCALL : Pseudo<(outs), (ins bare_symbol:$func)>; 1417 1418def : Pat<(loongarch_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>; 1419def : Pat<(loongarch_call texternalsym:$func), (PseudoCALL texternalsym:$func)>; 1420 1421// Function call with 'Medium' code model. 1422let isCall = 1, Defs = [R1, R20], Size = 8 in 1423def PseudoCALL_MEDIUM : Pseudo<(outs), (ins bare_symbol:$func)>; 1424 1425let Predicates = [IsLA64] in { 1426def : Pat<(loongarch_call_medium tglobaladdr:$func), 1427 (PseudoCALL_MEDIUM tglobaladdr:$func)>; 1428def : Pat<(loongarch_call_medium texternalsym:$func), 1429 (PseudoCALL_MEDIUM texternalsym:$func)>; 1430} // Predicates = [IsLA64] 1431 1432// Function call with 'Large' code model. 1433let isCall = 1, Defs = [R1, R20], Size = 24 in 1434def PseudoCALL_LARGE: Pseudo<(outs), (ins bare_symbol:$func)>; 1435 1436let Predicates = [IsLA64] in { 1437def : Pat<(loongarch_call_large tglobaladdr:$func), 1438 (PseudoCALL_LARGE tglobaladdr:$func)>; 1439def : Pat<(loongarch_call_large texternalsym:$func), 1440 (PseudoCALL_LARGE texternalsym:$func)>; 1441} // Predicates = [IsLA64] 1442 1443let isCall = 1, Defs = [R1] in 1444def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rj), 1445 [(loongarch_call GPR:$rj)]>, 1446 PseudoInstExpansion<(JIRL R1, GPR:$rj, 0)>; 1447let Predicates = [IsLA64] in { 1448def : Pat<(loongarch_call_medium GPR:$rj), (PseudoCALLIndirect GPR:$rj)>; 1449def : Pat<(loongarch_call_large GPR:$rj), (PseudoCALLIndirect GPR:$rj)>; 1450} 1451 1452let isCall = 1, hasSideEffects = 0, mayStore = 0, mayLoad = 0, Defs = [R1] in 1453def PseudoJIRL_CALL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>, 1454 PseudoInstExpansion<(JIRL R1, GPR:$rj, 1455 simm16_lsl2:$imm16)>; 1456 1457let isBarrier = 1, isReturn = 1, isTerminator = 1 in 1458def PseudoRET : Pseudo<(outs), (ins), [(loongarch_ret)]>, 1459 PseudoInstExpansion<(JIRL R0, R1, 0)>; 1460 1461// Tail call with 'Small' code model. 1462let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in 1463def PseudoTAIL : Pseudo<(outs), (ins bare_symbol:$dst)>; 1464 1465def : Pat<(loongarch_tail (iPTR tglobaladdr:$dst)), 1466 (PseudoTAIL tglobaladdr:$dst)>; 1467def : Pat<(loongarch_tail (iPTR texternalsym:$dst)), 1468 (PseudoTAIL texternalsym:$dst)>; 1469 1470// Tail call with 'Medium' code model. 1471let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, 1472 Uses = [R3], Defs = [R20], Size = 8 in 1473def PseudoTAIL_MEDIUM : Pseudo<(outs), (ins bare_symbol:$dst)>; 1474 1475let Predicates = [IsLA64] in { 1476def : Pat<(loongarch_tail_medium (iPTR tglobaladdr:$dst)), 1477 (PseudoTAIL_MEDIUM tglobaladdr:$dst)>; 1478def : Pat<(loongarch_tail_medium (iPTR texternalsym:$dst)), 1479 (PseudoTAIL_MEDIUM texternalsym:$dst)>; 1480} // Predicates = [IsLA64] 1481 1482// Tail call with 'Large' code model. 1483let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, 1484 Uses = [R3], Defs = [R19, R20], Size = 24 in 1485def PseudoTAIL_LARGE : Pseudo<(outs), (ins bare_symbol:$dst)>; 1486 1487let Predicates = [IsLA64] in { 1488def : Pat<(loongarch_tail_large (iPTR tglobaladdr:$dst)), 1489 (PseudoTAIL_LARGE tglobaladdr:$dst)>; 1490def : Pat<(loongarch_tail_large (iPTR texternalsym:$dst)), 1491 (PseudoTAIL_LARGE texternalsym:$dst)>; 1492} // Predicates = [IsLA64] 1493 1494let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3] in 1495def PseudoTAILIndirect : Pseudo<(outs), (ins GPRT:$rj), 1496 [(loongarch_tail GPRT:$rj)]>, 1497 PseudoInstExpansion<(JIRL R0, GPR:$rj, 0)>; 1498let Predicates = [IsLA64] in { 1499def : Pat<(loongarch_tail_medium GPR:$rj), (PseudoTAILIndirect GPR:$rj)>; 1500def : Pat<(loongarch_tail_large GPR:$rj), (PseudoTAILIndirect GPR:$rj)>; 1501} 1502 1503let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, 1504 hasSideEffects = 0, mayStore = 0, mayLoad = 0, Uses = [R3] in 1505def PseudoB_TAIL : Pseudo<(outs), (ins simm26_b:$imm26)>, 1506 PseudoInstExpansion<(B simm26_b:$imm26)>; 1507 1508let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, 1509 hasSideEffects = 0, mayStore = 0, mayLoad = 0, Uses = [R3] in 1510def PseudoJIRL_TAIL : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>, 1511 PseudoInstExpansion<(JIRL R0, GPR:$rj, 1512 simm16_lsl2:$imm16)>; 1513 1514/// call36/taill36 macro instructions 1515let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, isAsmParserOnly = 1, 1516 Defs = [R1], Size = 8, hasSideEffects = 0, mayStore = 0, mayLoad = 0 in 1517def PseudoCALL36 : Pseudo<(outs), (ins bare_symbol:$dst), [], 1518 "call36", "$dst">, 1519 Requires<[IsLA64]>; 1520let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [R3], 1521 isCodeGenOnly = 0, isAsmParserOnly = 1, Size = 8, hasSideEffects = 0, 1522 mayStore = 0, mayLoad = 0 in 1523def PseudoTAIL36 : Pseudo<(outs), (ins GPR:$tmp, bare_symbol:$dst), [], 1524 "tail36", "$tmp, $dst">, 1525 Requires<[IsLA64]>; 1526 1527/// Load address (la*) macro instructions. 1528 1529// Define isCodeGenOnly = 0 to expose them to tablegened assembly parser. 1530let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0, 1531 isAsmParserOnly = 1 in { 1532def PseudoLA_ABS : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1533 "la.abs", "$dst, $src">; 1534def PseudoLA_ABS_LARGE : Pseudo<(outs GPR:$dst), 1535 (ins GPR:$tmp, bare_symbol:$src), [], 1536 "la.abs", "$dst, $src">; 1537def PseudoLA_PCREL : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1538 "la.pcrel", "$dst, $src">; 1539let Defs = [R20], Size = 20 in 1540def PseudoLA_PCREL_LARGE : Pseudo<(outs GPR:$dst), 1541 (ins GPR:$tmp, bare_symbol:$src), [], 1542 "la.pcrel", "$dst, $tmp, $src">, 1543 Requires<[IsLA64]>; 1544def PseudoLA_TLS_LE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1545 "la.tls.le", "$dst, $src">; 1546} 1547let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0, 1548 isAsmParserOnly = 1 in { 1549def PseudoLA_GOT : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1550 "la.got", "$dst, $src">; 1551def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1552 "la.tls.ie", "$dst, $src">; 1553def PseudoLA_TLS_LD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1554 "la.tls.ld", "$dst, $src">; 1555def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1556 "la.tls.gd", "$dst, $src">; 1557let Defs = [R20], Size = 20 in { 1558def PseudoLA_GOT_LARGE : Pseudo<(outs GPR:$dst), 1559 (ins GPR:$tmp, bare_symbol:$src), [], 1560 "la.got", "$dst, $tmp, $src">, 1561 Requires<[IsLA64]>; 1562def PseudoLA_TLS_IE_LARGE : Pseudo<(outs GPR:$dst), 1563 (ins GPR:$tmp, bare_symbol:$src), [], 1564 "la.tls.ie", "$dst, $tmp, $src">, 1565 Requires<[IsLA64]>; 1566def PseudoLA_TLS_LD_LARGE : Pseudo<(outs GPR:$dst), 1567 (ins GPR:$tmp, bare_symbol:$src), [], 1568 "la.tls.ld", "$dst, $tmp, $src">, 1569 Requires<[IsLA64]>; 1570def PseudoLA_TLS_GD_LARGE : Pseudo<(outs GPR:$dst), 1571 (ins GPR:$tmp, bare_symbol:$src), [], 1572 "la.tls.gd", "$dst, $tmp, $src">, 1573 Requires<[IsLA64]>; 1574} // Defs = [R20], Size = 20 1575} 1576 1577// Load address inst alias: "la", "la.global" and "la.local". 1578// Default: 1579// la = la.global = la.got 1580// la.local = la.pcrel 1581// With feature "+la-global-with-pcrel": 1582// la = la.global = la.pcrel 1583// With feature "+la-global-with-abs": 1584// la = la.global = la.abs 1585// With feature "+la-local-with-abs": 1586// la.local = la.abs 1587// With features "+la-global-with-pcrel,+la-global-with-abs"(disorder): 1588// la = la.global = la.pcrel 1589// Note: To keep consistent with gnu-as behavior, the "la" can only have one 1590// register operand. 1591def : InstAlias<"la $dst, $src", (PseudoLA_GOT GPR:$dst, bare_symbol:$src)>; 1592def : InstAlias<"la.global $dst, $src", 1593 (PseudoLA_GOT GPR:$dst, bare_symbol:$src)>; 1594def : InstAlias<"la.global $dst, $tmp, $src", 1595 (PseudoLA_GOT_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>; 1596def : InstAlias<"la.local $dst, $src", 1597 (PseudoLA_PCREL GPR:$dst, bare_symbol:$src)>; 1598def : InstAlias<"la.local $dst, $tmp, $src", 1599 (PseudoLA_PCREL_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>; 1600 1601// Note: Keep HasLaGlobalWithPcrel before HasLaGlobalWithAbs to ensure 1602// "la-global-with-pcrel" takes effect when bose "la-global-with-pcrel" and 1603// "la-global-with-abs" are enabled. 1604let Predicates = [HasLaGlobalWithPcrel] in { 1605def : InstAlias<"la $dst, $src", (PseudoLA_PCREL GPR:$dst, bare_symbol:$src)>; 1606def : InstAlias<"la.global $dst, $src", 1607 (PseudoLA_PCREL GPR:$dst, bare_symbol:$src)>; 1608def : InstAlias<"la.global $dst, $tmp, $src", 1609 (PseudoLA_PCREL_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>; 1610} // Predicates = [HasLaGlobalWithPcrel] 1611 1612let Predicates = [HasLaGlobalWithAbs] in { 1613def : InstAlias<"la $dst, $src", (PseudoLA_ABS GPR:$dst, bare_symbol:$src)>; 1614def : InstAlias<"la.global $dst, $src", 1615 (PseudoLA_ABS GPR:$dst, bare_symbol:$src)>; 1616def : InstAlias<"la.global $dst, $tmp, $src", 1617 (PseudoLA_ABS_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>; 1618} // Predicates = [HasLaGlobalWithAbs] 1619 1620let Predicates = [HasLaLocalWithAbs] in { 1621def : InstAlias<"la.local $dst, $src", 1622 (PseudoLA_ABS GPR:$dst, bare_symbol:$src)>; 1623def : InstAlias<"la.local $dst, $tmp, $src", 1624 (PseudoLA_ABS_LARGE GPR:$dst, GPR:$tmp, bare_symbol:$src)>; 1625} // Predicates = [HasLaLocalWithAbs] 1626 1627/// BSTRINS and BSTRPICK 1628 1629let Predicates = [IsLA32] in { 1630def : Pat<(loongarch_bstrins GPR:$rd, GPR:$rj, uimm5:$msbd, uimm5:$lsbd), 1631 (BSTRINS_W GPR:$rd, GPR:$rj, uimm5:$msbd, uimm5:$lsbd)>; 1632def : Pat<(loongarch_bstrpick GPR:$rj, uimm5:$msbd, uimm5:$lsbd), 1633 (BSTRPICK_W GPR:$rj, uimm5:$msbd, uimm5:$lsbd)>; 1634} // Predicates = [IsLA32] 1635 1636let Predicates = [IsLA64] in { 1637def : Pat<(loongarch_bstrins GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd), 1638 (BSTRINS_D GPR:$rd, GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>; 1639def : Pat<(loongarch_bstrpick GPR:$rj, uimm6:$msbd, uimm6:$lsbd), 1640 (BSTRPICK_D GPR:$rj, uimm6:$msbd, uimm6:$lsbd)>; 1641} // Predicates = [IsLA64] 1642 1643/// Byte-swapping and bit-reversal 1644 1645def : Pat<(loongarch_revb_2h GPR:$rj), (REVB_2H GPR:$rj)>; 1646def : Pat<(loongarch_bitrev_4b GPR:$rj), (BITREV_4B GPR:$rj)>; 1647 1648let Predicates = [IsLA32] in { 1649def : Pat<(bswap GPR:$rj), (ROTRI_W (REVB_2H GPR:$rj), 16)>; 1650def : Pat<(bitreverse GPR:$rj), (BITREV_W GPR:$rj)>; 1651def : Pat<(bswap (bitreverse GPR:$rj)), (BITREV_4B GPR:$rj)>; 1652def : Pat<(bitreverse (bswap GPR:$rj)), (BITREV_4B GPR:$rj)>; 1653} // Predicates = [IsLA32] 1654 1655let Predicates = [IsLA64] in { 1656def : Pat<(loongarch_revb_2w GPR:$rj), (REVB_2W GPR:$rj)>; 1657def : Pat<(bswap GPR:$rj), (REVB_D GPR:$rj)>; 1658def : Pat<(loongarch_bitrev_w GPR:$rj), (BITREV_W GPR:$rj)>; 1659def : Pat<(bitreverse GPR:$rj), (BITREV_D GPR:$rj)>; 1660def : Pat<(bswap (bitreverse GPR:$rj)), (BITREV_8B GPR:$rj)>; 1661def : Pat<(bitreverse (bswap GPR:$rj)), (BITREV_8B GPR:$rj)>; 1662} // Predicates = [IsLA64] 1663 1664/// Loads 1665 1666multiclass LdPat<PatFrag LoadOp, LAInst Inst, ValueType vt = GRLenVT> { 1667 def : Pat<(vt (LoadOp BaseAddr:$rj)), (Inst BaseAddr:$rj, 0)>; 1668 def : Pat<(vt (LoadOp (AddrConstant GPR:$rj, simm12:$imm12))), 1669 (Inst GPR:$rj, simm12:$imm12)>; 1670 def : Pat<(vt (LoadOp (AddLike BaseAddr:$rj, simm12:$imm12))), 1671 (Inst BaseAddr:$rj, simm12:$imm12)>; 1672} 1673 1674defm : LdPat<sextloadi8, LD_B>; 1675defm : LdPat<extloadi8, LD_B>; 1676defm : LdPat<sextloadi16, LD_H>; 1677defm : LdPat<extloadi16, LD_H>; 1678defm : LdPat<load, LD_W>, Requires<[IsLA32]>; 1679defm : LdPat<zextloadi8, LD_BU>; 1680defm : LdPat<zextloadi16, LD_HU>; 1681let Predicates = [IsLA64] in { 1682defm : LdPat<sextloadi32, LD_W, i64>; 1683defm : LdPat<extloadi32, LD_W, i64>; 1684defm : LdPat<zextloadi32, LD_WU, i64>; 1685defm : LdPat<load, LD_D, i64>; 1686} // Predicates = [IsLA64] 1687 1688// LA64 register-register-addressed loads 1689let Predicates = [IsLA64] in { 1690class RegRegLdPat<PatFrag LoadOp, LAInst Inst, ValueType vt> 1691 : Pat<(vt (LoadOp (add NonFIBaseAddr:$rj, GPR:$rk))), 1692 (Inst NonFIBaseAddr:$rj, GPR:$rk)>; 1693 1694def : RegRegLdPat<extloadi8, LDX_B, i64>; 1695def : RegRegLdPat<sextloadi8, LDX_B, i64>; 1696def : RegRegLdPat<zextloadi8, LDX_BU, i64>; 1697def : RegRegLdPat<extloadi16, LDX_H, i64>; 1698def : RegRegLdPat<sextloadi16, LDX_H, i64>; 1699def : RegRegLdPat<zextloadi16, LDX_HU, i64>; 1700def : RegRegLdPat<extloadi32, LDX_W, i64>; 1701def : RegRegLdPat<sextloadi32, LDX_W, i64>; 1702def : RegRegLdPat<zextloadi32, LDX_WU, i64>; 1703def : RegRegLdPat<load, LDX_D, i64>; 1704} // Predicates = [IsLA64] 1705 1706/// Stores 1707 1708multiclass StPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy, 1709 ValueType vt> { 1710 def : Pat<(StoreOp (vt StTy:$rd), BaseAddr:$rj), 1711 (Inst StTy:$rd, BaseAddr:$rj, 0)>; 1712 def : Pat<(StoreOp (vt StTy:$rs2), (AddrConstant GPR:$rj, simm12:$imm12)), 1713 (Inst StTy:$rs2, GPR:$rj, simm12:$imm12)>; 1714 def : Pat<(StoreOp (vt StTy:$rd), (AddLike BaseAddr:$rj, simm12:$imm12)), 1715 (Inst StTy:$rd, BaseAddr:$rj, simm12:$imm12)>; 1716} 1717 1718defm : StPat<truncstorei8, ST_B, GPR, GRLenVT>; 1719defm : StPat<truncstorei16, ST_H, GPR, GRLenVT>; 1720defm : StPat<store, ST_W, GPR, i32>, Requires<[IsLA32]>; 1721let Predicates = [IsLA64] in { 1722defm : StPat<truncstorei32, ST_W, GPR, i64>; 1723defm : StPat<store, ST_D, GPR, i64>; 1724} // Predicates = [IsLA64] 1725 1726let Predicates = [IsLA64] in { 1727def : Pat<(i64 (sextloadi32 (AddLike BaseAddr:$rj, simm14_lsl2:$imm14))), 1728 (LDPTR_W BaseAddr:$rj, simm14_lsl2:$imm14)>; 1729def : Pat<(i64 (load (AddLike BaseAddr:$rj, simm14_lsl2:$imm14))), 1730 (LDPTR_D BaseAddr:$rj, simm14_lsl2:$imm14)>; 1731def : Pat<(truncstorei32 (i64 GPR:$rd), 1732 (AddLike BaseAddr:$rj, simm14_lsl2:$imm14)), 1733 (STPTR_W GPR:$rd, BaseAddr:$rj, simm14_lsl2:$imm14)>; 1734def : Pat<(store (i64 GPR:$rd), (AddLike BaseAddr:$rj, simm14_lsl2:$imm14)), 1735 (STPTR_D GPR:$rd, BaseAddr:$rj, simm14_lsl2:$imm14)>; 1736} // Predicates = [IsLA64] 1737 1738// LA64 register-register-addressed stores 1739let Predicates = [IsLA64] in { 1740class RegRegStPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy, 1741 ValueType vt> 1742 : Pat<(StoreOp (vt StTy:$rd), (add NonFIBaseAddr:$rj, GPR:$rk)), 1743 (Inst StTy:$rd, NonFIBaseAddr:$rj, GPR:$rk)>; 1744 1745def : RegRegStPat<truncstorei8, STX_B, GPR, i64>; 1746def : RegRegStPat<truncstorei16, STX_H, GPR, i64>; 1747def : RegRegStPat<truncstorei32, STX_W, GPR, i64>; 1748def : RegRegStPat<store, STX_D, GPR, i64>; 1749} // Predicates = [IsLA64] 1750 1751/// Atomic loads and stores 1752 1753// DBAR hint encoding for LA664 and later micro-architectures, paraphrased from 1754// the Linux patch revealing it [1]: 1755// 1756// - Bit 4: kind of constraint (0: completion, 1: ordering) 1757// - Bit 3: barrier for previous read (0: true, 1: false) 1758// - Bit 2: barrier for previous write (0: true, 1: false) 1759// - Bit 1: barrier for succeeding read (0: true, 1: false) 1760// - Bit 0: barrier for succeeding write (0: true, 1: false) 1761// 1762// Hint 0x700: barrier for "read after read" from the same address, which is 1763// e.g. needed by LL-SC loops on older models. (DBAR 0x700 behaves the same as 1764// nop if such reordering is disabled on supporting newer models.) 1765// 1766// [1]: https://lore.kernel.org/loongarch/20230516124536.535343-1-chenhuacai@loongson.cn/ 1767// 1768// Implementations without support for the finer-granularity hints simply treat 1769// all as the full barrier (DBAR 0), so we can unconditionally start emiting the 1770// more precise hints right away. 1771 1772def : Pat<(atomic_fence 4, timm), (DBAR 0b10100)>; // acquire 1773def : Pat<(atomic_fence 5, timm), (DBAR 0b10010)>; // release 1774def : Pat<(atomic_fence 6, timm), (DBAR 0b10000)>; // acqrel 1775def : Pat<(atomic_fence 7, timm), (DBAR 0b10000)>; // seqcst 1776 1777defm : LdPat<atomic_load_8, LD_B>; 1778defm : LdPat<atomic_load_16, LD_H>; 1779defm : LdPat<atomic_load_32, LD_W>; 1780 1781class release_seqcst_store<PatFrag base> 1782 : PatFrag<(ops node:$val, node:$ptr), (base node:$val, node:$ptr), [{ 1783 AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getSuccessOrdering(); 1784 return isReleaseOrStronger(Ordering); 1785}]>; 1786 1787class unordered_monotonic_store<PatFrag base> 1788 : PatFrag<(ops node:$val, node:$ptr), (base node:$val, node:$ptr), [{ 1789 AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getSuccessOrdering(); 1790 return !isReleaseOrStronger(Ordering); 1791}]>; 1792 1793def atomic_store_release_seqcst_32 : release_seqcst_store<atomic_store_32>; 1794def atomic_store_release_seqcst_64 : release_seqcst_store<atomic_store_64>; 1795def atomic_store_unordered_monotonic_32 1796 : unordered_monotonic_store<atomic_store_32>; 1797def atomic_store_unordered_monotonic_64 1798 : unordered_monotonic_store<atomic_store_64>; 1799 1800defm : StPat<atomic_store_8, ST_B, GPR, GRLenVT>; 1801defm : StPat<atomic_store_16, ST_H, GPR, GRLenVT>; 1802defm : StPat<atomic_store_unordered_monotonic_32, ST_W, GPR, i32>, 1803 Requires<[IsLA32]>; 1804 1805def PseudoAtomicStoreW 1806 : Pseudo<(outs GPR:$dst), (ins GPR:$rk, GPR:$rj)>, 1807 PseudoInstExpansion<(AMSWAP__DB_W R0, GPR:$rk, GPRMemAtomic:$rj)>; 1808 1809def : Pat<(atomic_store_release_seqcst_32 GPR:$rj, GPR:$rk), 1810 (PseudoAtomicStoreW GPR:$rj, GPR:$rk)>; 1811 1812let Predicates = [IsLA64] in { 1813def PseudoAtomicStoreD 1814 : Pseudo<(outs GPR:$dst), (ins GPR:$rk, GPR:$rj)>, 1815 PseudoInstExpansion<(AMSWAP__DB_D R0, GPR:$rk, GPRMemAtomic:$rj)>; 1816 1817def : Pat<(atomic_store_release_seqcst_64 GPR:$rj, GPR:$rk), 1818 (PseudoAtomicStoreD GPR:$rj, GPR:$rk)>; 1819 1820defm : LdPat<atomic_load_64, LD_D>; 1821defm : StPat<atomic_store_unordered_monotonic_32, ST_W, GPR, i64>; 1822defm : StPat<atomic_store_unordered_monotonic_64, ST_D, GPR, i64>; 1823} // Predicates = [IsLA64] 1824 1825/// Atomic Ops 1826 1827class PseudoMaskedAM 1828 : Pseudo<(outs GPR:$res, GPR:$scratch), 1829 (ins GPR:$addr, GPR:$incr, GPR:$mask, grlenimm:$ordering)> { 1830 let Constraints = "@earlyclobber $res,@earlyclobber $scratch"; 1831 let mayLoad = 1; 1832 let mayStore = 1; 1833 let hasSideEffects = 0; 1834 let Size = 36; 1835} 1836 1837def PseudoMaskedAtomicSwap32 : PseudoMaskedAM; 1838def PseudoMaskedAtomicLoadAdd32 : PseudoMaskedAM; 1839def PseudoMaskedAtomicLoadSub32 : PseudoMaskedAM; 1840def PseudoMaskedAtomicLoadNand32 : PseudoMaskedAM; 1841 1842class PseudoAM : Pseudo<(outs GPR:$res, GPR:$scratch), 1843 (ins GPR:$addr, GPR:$incr, grlenimm:$ordering)> { 1844 let Constraints = "@earlyclobber $res,@earlyclobber $scratch"; 1845 let mayLoad = 1; 1846 let mayStore = 1; 1847 let hasSideEffects = 0; 1848 let Size = 24; 1849} 1850 1851def PseudoAtomicSwap32 : PseudoAM; 1852def PseudoAtomicLoadNand32 : PseudoAM; 1853def PseudoAtomicLoadNand64 : PseudoAM; 1854def PseudoAtomicLoadAdd32 : PseudoAM; 1855def PseudoAtomicLoadSub32 : PseudoAM; 1856def PseudoAtomicLoadAnd32 : PseudoAM; 1857def PseudoAtomicLoadOr32 : PseudoAM; 1858def PseudoAtomicLoadXor32 : PseudoAM; 1859 1860multiclass PseudoBinPat<string Op, Pseudo BinInst> { 1861 def : Pat<(!cast<PatFrag>(Op#"_monotonic") GPR:$addr, GPR:$incr), 1862 (BinInst GPR:$addr, GPR:$incr, 2)>; 1863 def : Pat<(!cast<PatFrag>(Op#"_acquire") GPR:$addr, GPR:$incr), 1864 (BinInst GPR:$addr, GPR:$incr, 4)>; 1865 def : Pat<(!cast<PatFrag>(Op#"_release") GPR:$addr, GPR:$incr), 1866 (BinInst GPR:$addr, GPR:$incr, 5)>; 1867 def : Pat<(!cast<PatFrag>(Op#"_acq_rel") GPR:$addr, GPR:$incr), 1868 (BinInst GPR:$addr, GPR:$incr, 6)>; 1869 def : Pat<(!cast<PatFrag>(Op#"_seq_cst") GPR:$addr, GPR:$incr), 1870 (BinInst GPR:$addr, GPR:$incr, 7)>; 1871} 1872 1873class PseudoMaskedAMUMinUMax 1874 : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2), 1875 (ins GPR:$addr, GPR:$incr, GPR:$mask, grlenimm:$ordering)> { 1876 let Constraints = "@earlyclobber $res,@earlyclobber $scratch1," 1877 "@earlyclobber $scratch2"; 1878 let mayLoad = 1; 1879 let mayStore = 1; 1880 let hasSideEffects = 0; 1881 let Size = 48; 1882} 1883 1884def PseudoMaskedAtomicLoadUMax32 : PseudoMaskedAMUMinUMax; 1885def PseudoMaskedAtomicLoadUMin32 : PseudoMaskedAMUMinUMax; 1886 1887class PseudoMaskedAMMinMax 1888 : Pseudo<(outs GPR:$res, GPR:$scratch1, GPR:$scratch2), 1889 (ins GPR:$addr, GPR:$incr, GPR:$mask, grlenimm:$sextshamt, 1890 grlenimm:$ordering)> { 1891 let Constraints = "@earlyclobber $res,@earlyclobber $scratch1," 1892 "@earlyclobber $scratch2"; 1893 let mayLoad = 1; 1894 let mayStore = 1; 1895 let hasSideEffects = 0; 1896 let Size = 56; 1897} 1898 1899def PseudoMaskedAtomicLoadMax32 : PseudoMaskedAMMinMax; 1900def PseudoMaskedAtomicLoadMin32 : PseudoMaskedAMMinMax; 1901 1902/// Compare and exchange 1903 1904class PseudoCmpXchg 1905 : Pseudo<(outs GPR:$res, GPR:$scratch), 1906 (ins GPR:$addr, GPR:$cmpval, GPR:$newval, grlenimm:$fail_order)> { 1907 let Constraints = "@earlyclobber $res,@earlyclobber $scratch"; 1908 let mayLoad = 1; 1909 let mayStore = 1; 1910 let hasSideEffects = 0; 1911 let Size = 36; 1912} 1913 1914def PseudoCmpXchg32 : PseudoCmpXchg; 1915def PseudoCmpXchg64 : PseudoCmpXchg; 1916 1917def PseudoMaskedCmpXchg32 1918 : Pseudo<(outs GPR:$res, GPR:$scratch), 1919 (ins GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, 1920 grlenimm:$fail_order)> { 1921 let Constraints = "@earlyclobber $res,@earlyclobber $scratch"; 1922 let mayLoad = 1; 1923 let mayStore = 1; 1924 let hasSideEffects = 0; 1925 let Size = 44; 1926} 1927 1928class PseudoMaskedAMMinMaxPat<Intrinsic intrin, Pseudo AMInst> 1929 : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt, 1930 timm:$ordering), 1931 (AMInst GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt, 1932 timm:$ordering)>; 1933 1934class AtomicPat<Intrinsic intrin, Pseudo AMInst> 1935 : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering), 1936 (AMInst GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering)>; 1937 1938// These atomic cmpxchg PatFrags only care about the failure ordering. 1939// The PatFrags defined by multiclass `ternary_atomic_op_ord` in 1940// TargetSelectionDAG.td care about the merged memory ordering that is the 1941// stronger one between success and failure. But for LoongArch LL-SC we only 1942// need to care about the failure ordering as explained in PR #67391. So we 1943// define these PatFrags that will be used to define cmpxchg pats below. 1944multiclass ternary_atomic_op_failure_ord { 1945 def NAME#_failure_monotonic : PatFrag<(ops node:$ptr, node:$cmp, node:$val), 1946 (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{ 1947 AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getFailureOrdering(); 1948 return Ordering == AtomicOrdering::Monotonic; 1949 }]>; 1950 def NAME#_failure_acquire : PatFrag<(ops node:$ptr, node:$cmp, node:$val), 1951 (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{ 1952 AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getFailureOrdering(); 1953 return Ordering == AtomicOrdering::Acquire; 1954 }]>; 1955 def NAME#_failure_release : PatFrag<(ops node:$ptr, node:$cmp, node:$val), 1956 (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{ 1957 AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getFailureOrdering(); 1958 return Ordering == AtomicOrdering::Release; 1959 }]>; 1960 def NAME#_failure_acq_rel : PatFrag<(ops node:$ptr, node:$cmp, node:$val), 1961 (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{ 1962 AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getFailureOrdering(); 1963 return Ordering == AtomicOrdering::AcquireRelease; 1964 }]>; 1965 def NAME#_failure_seq_cst : PatFrag<(ops node:$ptr, node:$cmp, node:$val), 1966 (!cast<SDPatternOperator>(NAME) node:$ptr, node:$cmp, node:$val), [{ 1967 AtomicOrdering Ordering = cast<AtomicSDNode>(N)->getFailureOrdering(); 1968 return Ordering == AtomicOrdering::SequentiallyConsistent; 1969 }]>; 1970} 1971 1972defm atomic_cmp_swap_32 : ternary_atomic_op_failure_ord; 1973defm atomic_cmp_swap_64 : ternary_atomic_op_failure_ord; 1974 1975let Predicates = [IsLA64] in { 1976def : AtomicPat<int_loongarch_masked_atomicrmw_xchg_i64, 1977 PseudoMaskedAtomicSwap32>; 1978def : Pat<(atomic_swap_32 GPR:$addr, GPR:$incr), 1979 (AMSWAP__DB_W GPR:$incr, GPR:$addr)>; 1980def : Pat<(atomic_swap_64 GPR:$addr, GPR:$incr), 1981 (AMSWAP__DB_D GPR:$incr, GPR:$addr)>; 1982def : Pat<(atomic_load_add_64 GPR:$rj, GPR:$rk), 1983 (AMADD__DB_D GPR:$rk, GPR:$rj)>; 1984def : AtomicPat<int_loongarch_masked_atomicrmw_add_i64, 1985 PseudoMaskedAtomicLoadAdd32>; 1986def : Pat<(atomic_load_sub_32 GPR:$rj, GPR:$rk), 1987 (AMADD__DB_W (SUB_W R0, GPR:$rk), GPR:$rj)>; 1988def : Pat<(atomic_load_sub_64 GPR:$rj, GPR:$rk), 1989 (AMADD__DB_D (SUB_D R0, GPR:$rk), GPR:$rj)>; 1990def : AtomicPat<int_loongarch_masked_atomicrmw_sub_i64, 1991 PseudoMaskedAtomicLoadSub32>; 1992defm : PseudoBinPat<"atomic_load_nand_64", PseudoAtomicLoadNand64>; 1993def : AtomicPat<int_loongarch_masked_atomicrmw_nand_i64, 1994 PseudoMaskedAtomicLoadNand32>; 1995def : Pat<(atomic_load_add_32 GPR:$rj, GPR:$rk), 1996 (AMADD__DB_W GPR:$rk, GPR:$rj)>; 1997def : Pat<(atomic_load_and_32 GPR:$rj, GPR:$rk), 1998 (AMAND__DB_W GPR:$rk, GPR:$rj)>; 1999def : Pat<(atomic_load_and_64 GPR:$rj, GPR:$rk), 2000 (AMAND__DB_D GPR:$rk, GPR:$rj)>; 2001def : Pat<(atomic_load_or_32 GPR:$rj, GPR:$rk), 2002 (AMOR__DB_W GPR:$rk, GPR:$rj)>; 2003def : Pat<(atomic_load_or_64 GPR:$rj, GPR:$rk), 2004 (AMOR__DB_D GPR:$rk, GPR:$rj)>; 2005def : Pat<(atomic_load_xor_32 GPR:$rj, GPR:$rk), 2006 (AMXOR__DB_W GPR:$rk, GPR:$rj)>; 2007def : Pat<(atomic_load_xor_64 GPR:$rj, GPR:$rk), 2008 (AMXOR__DB_D GPR:$rk, GPR:$rj)>; 2009 2010def : Pat<(atomic_load_umin_32 GPR:$rj, GPR:$rk), 2011 (AMMIN__DB_WU GPR:$rk, GPR:$rj)>; 2012def : Pat<(atomic_load_umin_64 GPR:$rj, GPR:$rk), 2013 (AMMIN__DB_DU GPR:$rk, GPR:$rj)>; 2014def : Pat<(atomic_load_umax_32 GPR:$rj, GPR:$rk), 2015 (AMMAX__DB_WU GPR:$rk, GPR:$rj)>; 2016def : Pat<(atomic_load_umax_64 GPR:$rj, GPR:$rk), 2017 (AMMAX__DB_DU GPR:$rk, GPR:$rj)>; 2018 2019def : Pat<(atomic_load_min_32 GPR:$rj, GPR:$rk), 2020 (AMMIN__DB_W GPR:$rk, GPR:$rj)>; 2021def : Pat<(atomic_load_min_64 GPR:$rj, GPR:$rk), 2022 (AMMIN__DB_D GPR:$rk, GPR:$rj)>; 2023def : Pat<(atomic_load_max_32 GPR:$rj, GPR:$rk), 2024 (AMMAX__DB_W GPR:$rk, GPR:$rj)>; 2025def : Pat<(atomic_load_max_64 GPR:$rj, GPR:$rk), 2026 (AMMAX__DB_D GPR:$rk, GPR:$rj)>; 2027 2028def : AtomicPat<int_loongarch_masked_atomicrmw_umax_i64, 2029 PseudoMaskedAtomicLoadUMax32>; 2030def : AtomicPat<int_loongarch_masked_atomicrmw_umin_i64, 2031 PseudoMaskedAtomicLoadUMin32>; 2032 2033// Ordering constants must be kept in sync with the AtomicOrdering enum in 2034// AtomicOrdering.h. 2035multiclass PseudoCmpXchgPat<string Op, Pseudo CmpXchgInst, 2036 ValueType vt = GRLenVT> { 2037 def : Pat<(vt (!cast<PatFrag>(Op#"_failure_monotonic") GPR:$addr, GPR:$cmp, GPR:$new)), 2038 (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 2)>; 2039 def : Pat<(vt (!cast<PatFrag>(Op#"_failure_acquire") GPR:$addr, GPR:$cmp, GPR:$new)), 2040 (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 4)>; 2041 def : Pat<(vt (!cast<PatFrag>(Op#"_failure_release") GPR:$addr, GPR:$cmp, GPR:$new)), 2042 (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 5)>; 2043 def : Pat<(vt (!cast<PatFrag>(Op#"_failure_acq_rel") GPR:$addr, GPR:$cmp, GPR:$new)), 2044 (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 6)>; 2045 def : Pat<(vt (!cast<PatFrag>(Op#"_failure_seq_cst") GPR:$addr, GPR:$cmp, GPR:$new)), 2046 (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 7)>; 2047} 2048 2049defm : PseudoCmpXchgPat<"atomic_cmp_swap_32", PseudoCmpXchg32>; 2050defm : PseudoCmpXchgPat<"atomic_cmp_swap_64", PseudoCmpXchg64, i64>; 2051def : Pat<(int_loongarch_masked_cmpxchg_i64 2052 GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$fail_order), 2053 (PseudoMaskedCmpXchg32 2054 GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$fail_order)>; 2055 2056def : PseudoMaskedAMMinMaxPat<int_loongarch_masked_atomicrmw_max_i64, 2057 PseudoMaskedAtomicLoadMax32>; 2058def : PseudoMaskedAMMinMaxPat<int_loongarch_masked_atomicrmw_min_i64, 2059 PseudoMaskedAtomicLoadMin32>; 2060} // Predicates = [IsLA64] 2061 2062defm : PseudoBinPat<"atomic_load_nand_32", PseudoAtomicLoadNand32>; 2063 2064let Predicates = [IsLA32] in { 2065def : AtomicPat<int_loongarch_masked_atomicrmw_xchg_i32, 2066 PseudoMaskedAtomicSwap32>; 2067defm : PseudoBinPat<"atomic_swap_32", PseudoAtomicSwap32>; 2068def : AtomicPat<int_loongarch_masked_atomicrmw_add_i32, 2069 PseudoMaskedAtomicLoadAdd32>; 2070def : AtomicPat<int_loongarch_masked_atomicrmw_sub_i32, 2071 PseudoMaskedAtomicLoadSub32>; 2072def : AtomicPat<int_loongarch_masked_atomicrmw_nand_i32, 2073 PseudoMaskedAtomicLoadNand32>; 2074defm : PseudoBinPat<"atomic_load_add_32", PseudoAtomicLoadAdd32>; 2075defm : PseudoBinPat<"atomic_load_sub_32", PseudoAtomicLoadSub32>; 2076defm : PseudoBinPat<"atomic_load_and_32", PseudoAtomicLoadAnd32>; 2077defm : PseudoBinPat<"atomic_load_or_32", PseudoAtomicLoadOr32>; 2078defm : PseudoBinPat<"atomic_load_xor_32", PseudoAtomicLoadXor32>; 2079} // Predicates = [IsLA32] 2080 2081/// Intrinsics 2082 2083def : Pat<(int_loongarch_cacop_d timm:$op, i64:$rj, timm:$imm12), 2084 (CACOP timm:$op, GPR:$rj, timm:$imm12)>; 2085def : Pat<(int_loongarch_cacop_w i32:$op, i32:$rj, i32:$imm12), 2086 (CACOP timm:$op, GPR:$rj, timm:$imm12)>; 2087def : Pat<(loongarch_dbar uimm15:$imm15), (DBAR uimm15:$imm15)>; 2088def : Pat<(loongarch_ibar uimm15:$imm15), (IBAR uimm15:$imm15)>; 2089def : Pat<(loongarch_break uimm15:$imm15), (BREAK uimm15:$imm15)>; 2090def : Pat<(loongarch_syscall uimm15:$imm15), (SYSCALL uimm15:$imm15)>; 2091 2092let Predicates = [IsLA64] in { 2093// CRC Check Instructions 2094def : PatGprGpr<loongarch_crc_w_b_w, CRC_W_B_W>; 2095def : PatGprGpr<loongarch_crc_w_h_w, CRC_W_H_W>; 2096def : PatGprGpr<loongarch_crc_w_w_w, CRC_W_W_W>; 2097def : PatGprGpr<loongarch_crc_w_d_w, CRC_W_D_W>; 2098def : PatGprGpr<loongarch_crcc_w_b_w, CRCC_W_B_W>; 2099def : PatGprGpr<loongarch_crcc_w_h_w, CRCC_W_H_W>; 2100def : PatGprGpr<loongarch_crcc_w_w_w, CRCC_W_W_W>; 2101def : PatGprGpr<loongarch_crcc_w_d_w, CRCC_W_D_W>; 2102} // Predicates = [IsLA64] 2103 2104/// Other pseudo-instructions 2105 2106// Pessimistically assume the stack pointer will be clobbered 2107let Defs = [R3], Uses = [R3] in { 2108def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 2109 [(callseq_start timm:$amt1, timm:$amt2)]>; 2110def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 2111 [(callseq_end timm:$amt1, timm:$amt2)]>; 2112} // Defs = [R3], Uses = [R3] 2113 2114//===----------------------------------------------------------------------===// 2115// Assembler Pseudo Instructions 2116//===----------------------------------------------------------------------===// 2117 2118def : InstAlias<"nop", (ANDI R0, R0, 0)>; 2119def : InstAlias<"move $dst, $src", (OR GPR:$dst, GPR:$src, R0)>; 2120// `ret` is supported since binutils commit 20f2e2686c79a5ac (version 2.40 and 2121// later). 2122def : InstAlias<"ret", (JIRL R0, R1, 0)>; 2123def : InstAlias<"jr $rj", (JIRL R0, GPR:$rj, 0)>; 2124 2125// Branches implemented with alias. 2126// Always output the canonical mnemonic for the pseudo branch instructions. 2127// The GNU tools emit the canonical mnemonic for the branch pseudo instructions 2128// as well (e.g. "bgt" will be recognised by the assembler but never printed by 2129// objdump). Match this behaviour by setting a zero weight. 2130def : InstAlias<"bgt $rj, $rd, $imm16", 2131 (BLT GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>; 2132def : InstAlias<"bgtu $rj, $rd, $imm16", 2133 (BLTU GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>; 2134def : InstAlias<"ble $rj, $rd, $imm16", 2135 (BGE GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>; 2136def : InstAlias<"bleu $rj, $rd, $imm16", 2137 (BGEU GPR:$rd, GPR:$rj, simm16_lsl2_br:$imm16), 0>; 2138def : InstAlias<"bltz $rd, $imm16", 2139 (BLT GPR:$rd, R0, simm16_lsl2_br:$imm16), 0>; 2140def : InstAlias<"bgtz $rj, $imm16", 2141 (BLT R0, GPR:$rj, simm16_lsl2_br:$imm16), 0>; 2142def : InstAlias<"blez $rj, $imm16", 2143 (BGE R0, GPR:$rj, simm16_lsl2_br:$imm16), 0>; 2144def : InstAlias<"bgez $rd, $imm16", 2145 (BGE GPR:$rd, R0, simm16_lsl2_br:$imm16), 0>; 2146 2147// Load immediate. 2148let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0, 2149 isAsmParserOnly = 1 in { 2150def PseudoLI_W : Pseudo<(outs GPR:$rd), (ins imm32:$imm), [], 2151 "li.w", "$rd, $imm">; 2152def PseudoLI_D : Pseudo<(outs GPR:$rd), (ins grlenimm:$imm), [], 2153 "li.d", "$rd, $imm">, Requires<[IsLA64]>; 2154} 2155 2156//===----------------------------------------------------------------------===// 2157// Basic Floating-Point Instructions 2158//===----------------------------------------------------------------------===// 2159 2160include "LoongArchFloat32InstrInfo.td" 2161include "LoongArchFloat64InstrInfo.td" 2162 2163let Predicates = [HasBasicF], usesCustomInserter = 1 in { 2164 def WRFCSR : Pseudo<(outs), (ins uimm2:$fcsr, GPR:$src), 2165 [(loongarch_movgr2fcsr uimm2:$fcsr, GRLenVT:$src)]>; 2166 def RDFCSR : Pseudo<(outs GPR:$rd), (ins uimm2:$fcsr), 2167 [(set GPR:$rd, (loongarch_movfcsr2gr uimm2:$fcsr))]>; 2168} 2169 2170//===----------------------------------------------------------------------===// 2171// Privilege Instructions 2172//===----------------------------------------------------------------------===// 2173 2174// CSR Access Instructions 2175let hasSideEffects = 1 in 2176def CSRRD : FmtCSR<0x04000000, (outs GPR:$rd), (ins uimm14:$csr_num), 2177 "$rd, $csr_num">; 2178let hasSideEffects = 1, Constraints = "$rd = $dst" in { 2179def CSRWR : FmtCSR<0x04000020, (outs GPR:$dst), 2180 (ins GPR:$rd, uimm14:$csr_num), "$rd, $csr_num">; 2181def CSRXCHG : FmtCSRXCHG<0x04000000, (outs GPR:$dst), 2182 (ins GPR:$rd, GPR:$rj, uimm14:$csr_num), 2183 "$rd, $rj, $csr_num">; 2184} // hasSideEffects = 1, Constraints = "$rd = $dst" 2185 2186// IOCSR Access Instructions 2187def IOCSRRD_B : IOCSRRD<0x06480000>; 2188def IOCSRRD_H : IOCSRRD<0x06480400>; 2189def IOCSRRD_W : IOCSRRD<0x06480800>; 2190def IOCSRWR_B : IOCSRWR<0x06481000>; 2191def IOCSRWR_H : IOCSRWR<0x06481400>; 2192def IOCSRWR_W : IOCSRWR<0x06481800>; 2193let Predicates = [IsLA64] in { 2194def IOCSRRD_D : IOCSRRD<0x06480c00>; 2195def IOCSRWR_D : IOCSRWR<0x06481c00>; 2196} // Predicates = [IsLA64] 2197 2198// TLB Maintenance Instructions 2199let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in { 2200def TLBSRCH : FmtI32<0x06482800>; 2201def TLBRD : FmtI32<0x06482c00>; 2202def TLBWR : FmtI32<0x06483000>; 2203def TLBFILL : FmtI32<0x06483400>; 2204def TLBCLR : FmtI32<0x06482000>; 2205def TLBFLUSH : FmtI32<0x06482400>; 2206def INVTLB : FmtINVTLB<(outs), (ins GPR:$rk, GPR:$rj, uimm5:$op), 2207 "$op, $rj, $rk">; 2208} // hasSideEffects = 1, mayLoad = 0, mayStore = 0 2209 2210// Software Page Walking Instructions 2211def LDDIR : Fmt2RI8<0x06400000, (outs GPR:$rd), 2212 (ins GPR:$rj, uimm8:$imm8), "$rd, $rj, $imm8">; 2213def LDPTE : FmtLDPTE<(outs), (ins GPR:$rj, uimm8:$seq), "$rj, $seq">; 2214 2215 2216// Other Miscellaneous Instructions 2217let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 2218def ERTN : FmtI32<0x06483800>; 2219def DBCL : MISC_I15<0x002a8000>; 2220def IDLE : MISC_I15<0x06488000>; 2221 2222//===----------------------------------------------------------------------===// 2223// Privilege Intrinsics 2224//===----------------------------------------------------------------------===// 2225 2226def : Pat<(loongarch_csrrd uimm14:$imm14), (CSRRD uimm14:$imm14)>; 2227def : Pat<(loongarch_csrwr GPR:$rd, uimm14:$imm14), 2228 (CSRWR GPR:$rd, uimm14:$imm14)>; 2229def : Pat<(loongarch_csrxchg GPR:$rd, GPR:$rj, uimm14:$imm14), 2230 (CSRXCHG GPR:$rd, GPR:$rj, uimm14:$imm14)>; 2231 2232def : Pat<(loongarch_iocsrrd_b GPR:$rj), (IOCSRRD_B GPR:$rj)>; 2233def : Pat<(loongarch_iocsrrd_h GPR:$rj), (IOCSRRD_H GPR:$rj)>; 2234def : Pat<(loongarch_iocsrrd_w GPR:$rj), (IOCSRRD_W GPR:$rj)>; 2235 2236def : Pat<(loongarch_iocsrwr_b GPR:$rd, GPR:$rj), (IOCSRWR_B GPR:$rd, GPR:$rj)>; 2237def : Pat<(loongarch_iocsrwr_h GPR:$rd, GPR:$rj), (IOCSRWR_H GPR:$rd, GPR:$rj)>; 2238def : Pat<(loongarch_iocsrwr_w GPR:$rd, GPR:$rj), (IOCSRWR_W GPR:$rd, GPR:$rj)>; 2239 2240def : Pat<(loongarch_cpucfg GPR:$rj), (CPUCFG GPR:$rj)>; 2241 2242let Predicates = [IsLA64] in { 2243def : Pat<(loongarch_iocsrrd_d GPR:$rj), (IOCSRRD_D GPR:$rj)>; 2244def : Pat<(loongarch_iocsrwr_d GPR:$rd, GPR:$rj), (IOCSRWR_D GPR:$rd, GPR:$rj)>; 2245def : Pat<(int_loongarch_asrtle_d GPR:$rj, GPR:$rk), 2246 (ASRTLE_D GPR:$rj, GPR:$rk)>; 2247def : Pat<(int_loongarch_asrtgt_d GPR:$rj, GPR:$rk), 2248 (ASRTGT_D GPR:$rj, GPR:$rk)>; 2249def : Pat<(int_loongarch_lddir_d GPR:$rj, timm:$imm8), 2250 (LDDIR GPR:$rj, timm:$imm8)>; 2251def : Pat<(int_loongarch_ldpte_d GPR:$rj, timm:$imm8), 2252 (LDPTE GPR:$rj, timm:$imm8)>; 2253} // Predicates = [IsLA64] 2254 2255//===----------------------------------------------------------------------===// 2256// LSX Instructions 2257//===----------------------------------------------------------------------===// 2258include "LoongArchLSXInstrInfo.td" 2259 2260//===----------------------------------------------------------------------===// 2261// LASX Instructions 2262//===----------------------------------------------------------------------===// 2263include "LoongArchLASXInstrInfo.td" 2264 2265//===----------------------------------------------------------------------===// 2266// LVZ Instructions 2267//===----------------------------------------------------------------------===// 2268include "LoongArchLVZInstrInfo.td" 2269 2270//===----------------------------------------------------------------------===// 2271// LBT Instructions 2272//===----------------------------------------------------------------------===// 2273include "LoongArchLBTInstrInfo.td" 2274