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