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