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