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