1//===-- RISCVInstrInfo.td - Target Description for RISC-V --*- 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 RISC-V instructions in TableGen format. 10// 11//===----------------------------------------------------------------------===// 12 13//===----------------------------------------------------------------------===// 14// RISC-V 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_RISCVCall : SDTypeProfile<0, -1, [SDTCisVT<0, XLenVT>]>; 25def SDT_RISCVSelectCC : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>, 26 SDTCisVT<3, OtherVT>, 27 SDTCisSameAs<0, 4>, 28 SDTCisSameAs<4, 5>]>; 29def SDT_RISCVBrCC : SDTypeProfile<0, 4, [SDTCisSameAs<0, 1>, 30 SDTCisVT<2, OtherVT>, 31 SDTCisVT<3, OtherVT>]>; 32def SDT_RISCVReadCSR : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisInt<1>]>; 33def SDT_RISCVWriteCSR : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisInt<1>]>; 34def SDT_RISCVSwapCSR : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisInt<1>, 35 SDTCisInt<2>]>; 36def SDT_RISCVReadCounterWide : SDTypeProfile<2, 2, [SDTCisVT<0, i32>, 37 SDTCisVT<1, i32>, 38 SDTCisInt<2>, 39 SDTCisInt<3>]>; 40def SDT_RISCVIntUnaryOpW : SDTypeProfile<1, 1, [ 41 SDTCisSameAs<0, 1>, SDTCisVT<0, i64> 42]>; 43def SDT_RISCVIntBinOpW : SDTypeProfile<1, 2, [ 44 SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64> 45]>; 46def SDT_RISCVIntShiftDOpW : SDTypeProfile<1, 3, [ 47 SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64>, SDTCisVT<3, i64> 48]>; 49 50// Target-independent nodes, but with target-specific formats. 51def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart, 52 [SDNPHasChain, SDNPOutGlue]>; 53def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd, 54 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; 55 56// Target-dependent nodes. 57def riscv_call : SDNode<"RISCVISD::CALL", SDT_RISCVCall, 58 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 59 SDNPVariadic]>; 60def riscv_ret_glue : SDNode<"RISCVISD::RET_GLUE", SDTNone, 61 [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; 62def riscv_sret_glue : SDNode<"RISCVISD::SRET_GLUE", SDTNone, 63 [SDNPHasChain, SDNPOptInGlue]>; 64def riscv_mret_glue : SDNode<"RISCVISD::MRET_GLUE", SDTNone, 65 [SDNPHasChain, SDNPOptInGlue]>; 66def riscv_selectcc : SDNode<"RISCVISD::SELECT_CC", SDT_RISCVSelectCC>; 67def riscv_brcc : SDNode<"RISCVISD::BR_CC", SDT_RISCVBrCC, 68 [SDNPHasChain]>; 69def riscv_tail : SDNode<"RISCVISD::TAIL", SDT_RISCVCall, 70 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 71 SDNPVariadic]>; 72def riscv_sw_guarded_brind : SDNode<"RISCVISD::SW_GUARDED_BRIND", 73 SDTBrind, [SDNPHasChain]>; 74def riscv_sllw : SDNode<"RISCVISD::SLLW", SDT_RISCVIntBinOpW>; 75def riscv_sraw : SDNode<"RISCVISD::SRAW", SDT_RISCVIntBinOpW>; 76def riscv_srlw : SDNode<"RISCVISD::SRLW", SDT_RISCVIntBinOpW>; 77def riscv_read_csr : SDNode<"RISCVISD::READ_CSR", SDT_RISCVReadCSR, 78 [SDNPHasChain]>; 79def riscv_write_csr : SDNode<"RISCVISD::WRITE_CSR", SDT_RISCVWriteCSR, 80 [SDNPHasChain]>; 81def riscv_swap_csr : SDNode<"RISCVISD::SWAP_CSR", SDT_RISCVSwapCSR, 82 [SDNPHasChain]>; 83 84def riscv_read_counter_wide : SDNode<"RISCVISD::READ_COUNTER_WIDE", 85 SDT_RISCVReadCounterWide, 86 [SDNPHasChain, SDNPSideEffect]>; 87 88def riscv_add_lo : SDNode<"RISCVISD::ADD_LO", SDTIntBinOp>; 89def riscv_hi : SDNode<"RISCVISD::HI", SDTIntUnaryOp>; 90def riscv_lla : SDNode<"RISCVISD::LLA", SDTIntUnaryOp>; 91def riscv_add_tprel : SDNode<"RISCVISD::ADD_TPREL", 92 SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, 93 SDTCisSameAs<0, 2>, 94 SDTCisSameAs<0, 3>, 95 SDTCisInt<0>]>>; 96 97//===----------------------------------------------------------------------===// 98// Operand and SDNode transformation definitions. 99//===----------------------------------------------------------------------===// 100 101class ImmXLenAsmOperand<string prefix, string suffix = ""> : AsmOperandClass { 102 let Name = prefix # "ImmXLen" # suffix; 103 let RenderMethod = "addImmOperands"; 104 let DiagnosticType = !strconcat("Invalid", Name); 105} 106 107class ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass { 108 let Name = prefix # "Imm" # width # suffix; 109 let RenderMethod = "addImmOperands"; 110 let DiagnosticType = !strconcat("Invalid", Name); 111} 112 113def ImmZeroAsmOperand : AsmOperandClass { 114 let Name = "ImmZero"; 115 let RenderMethod = "addImmOperands"; 116 let DiagnosticType = !strconcat("Invalid", Name); 117} 118 119// A parse method for (${gpr}) or 0(${gpr}), where the 0 is be silently ignored. 120def ZeroOffsetMemOpOperand : AsmOperandClass { 121 let Name = "ZeroOffsetMemOpOperand"; 122 let RenderMethod = "addRegOperands"; 123 let PredicateMethod = "isGPR"; 124 let ParserMethod = "parseZeroOffsetMemOp"; 125} 126 127class MemOperand<RegisterClass regClass> : RegisterOperand<regClass>{ 128 let OperandType = "OPERAND_MEMORY"; 129} 130 131def GPRMemZeroOffset : MemOperand<GPR> { 132 let ParserMatchClass = ZeroOffsetMemOpOperand; 133 let PrintMethod = "printZeroOffsetMemOp"; 134} 135 136def GPRMem : MemOperand<GPR>; 137 138def SPMem : MemOperand<SP>; 139 140def GPRCMem : MemOperand<GPRC>; 141 142class SImmAsmOperand<int width, string suffix = ""> 143 : ImmAsmOperand<"S", width, suffix> { 144} 145 146class UImmAsmOperand<int width, string suffix = ""> 147 : ImmAsmOperand<"U", width, suffix> { 148} 149 150class RISCVOp<ValueType vt = XLenVT> : Operand<vt> { 151 let OperandNamespace = "RISCVOp"; 152} 153 154class RISCVUImmOp<int bitsNum> : RISCVOp { 155 let ParserMatchClass = UImmAsmOperand<bitsNum>; 156 let DecoderMethod = "decodeUImmOperand<" # bitsNum # ">"; 157 let OperandType = "OPERAND_UIMM" # bitsNum; 158} 159 160class RISCVUImmLeafOp<int bitsNum> : 161 RISCVUImmOp<bitsNum>, ImmLeaf<XLenVT, "return isUInt<" # bitsNum # ">(Imm);">; 162 163class RISCVSImmOp<int bitsNum> : RISCVOp { 164 let ParserMatchClass = SImmAsmOperand<bitsNum>; 165 let EncoderMethod = "getImmOpValue"; 166 let DecoderMethod = "decodeSImmOperand<" # bitsNum # ">"; 167 let OperandType = "OPERAND_SIMM" # bitsNum; 168} 169 170class RISCVSImmLeafOp<int bitsNum> : 171 RISCVSImmOp<bitsNum>, ImmLeaf<XLenVT, "return isInt<" # bitsNum # ">(Imm);">; 172 173def FenceArg : AsmOperandClass { 174 let Name = "FenceArg"; 175 let RenderMethod = "addFenceArgOperands"; 176 let ParserMethod = "parseFenceArg"; 177} 178 179def fencearg : RISCVOp { 180 let ParserMatchClass = FenceArg; 181 let PrintMethod = "printFenceArg"; 182 let DecoderMethod = "decodeUImmOperand<4>"; 183 let OperandType = "OPERAND_UIMM4"; 184} 185 186def UImmLog2XLenAsmOperand : AsmOperandClass { 187 let Name = "UImmLog2XLen"; 188 let RenderMethod = "addImmOperands"; 189 let DiagnosticType = "InvalidUImmLog2XLen"; 190} 191 192def uimmlog2xlen : RISCVOp, ImmLeaf<XLenVT, [{ 193 if (Subtarget->is64Bit()) 194 return isUInt<6>(Imm); 195 return isUInt<5>(Imm); 196}]> { 197 let ParserMatchClass = UImmLog2XLenAsmOperand; 198 // TODO: should ensure invalid shamt is rejected when decoding. 199 let DecoderMethod = "decodeUImmOperand<6>"; 200 let MCOperandPredicate = [{ 201 int64_t Imm; 202 if (!MCOp.evaluateAsConstantImm(Imm)) 203 return false; 204 if (STI.getTargetTriple().isArch64Bit()) 205 return isUInt<6>(Imm); 206 return isUInt<5>(Imm); 207 }]; 208 let OperandType = "OPERAND_UIMMLOG2XLEN"; 209} 210 211def InsnDirectiveOpcode : AsmOperandClass { 212 let Name = "InsnDirectiveOpcode"; 213 let ParserMethod = "parseInsnDirectiveOpcode"; 214 let RenderMethod = "addImmOperands"; 215 let PredicateMethod = "isImm"; 216} 217 218def uimm1 : RISCVUImmLeafOp<1>; 219def uimm2 : RISCVUImmLeafOp<2> { 220 let MCOperandPredicate = [{ 221 int64_t Imm; 222 if (!MCOp.evaluateAsConstantImm(Imm)) 223 return false; 224 return isUInt<2>(Imm); 225 }]; 226} 227def uimm3 : RISCVUImmOp<3>; 228def uimm4 : RISCVUImmOp<4>; 229def uimm5 : RISCVUImmLeafOp<5>; 230def uimm6 : RISCVUImmLeafOp<6>; 231def uimm7_opcode : RISCVUImmOp<7> { 232 let ParserMatchClass = InsnDirectiveOpcode; 233} 234def uimm7 : RISCVUImmOp<7>; 235def uimm8 : RISCVUImmOp<8>; 236def uimm16 : RISCVUImmOp<16>; 237def uimm32 : RISCVUImmOp<32>; 238def simm12 : RISCVSImmLeafOp<12> { 239 let MCOperandPredicate = [{ 240 int64_t Imm; 241 if (MCOp.evaluateAsConstantImm(Imm)) 242 return isInt<12>(Imm); 243 return MCOp.isBareSymbolRef(); 244 }]; 245} 246 247// A 12-bit signed immediate which cannot fit in 6-bit signed immediate, 248// but even negative value fit in 12-bit. 249def simm12_no6 : ImmLeaf<XLenVT, [{ 250 return isInt<12>(Imm) && !isInt<6>(Imm) && isInt<12>(-Imm);}]>; 251 252// A 13-bit signed immediate where the least significant bit is zero. 253def simm13_lsb0 : Operand<OtherVT> { 254 let ParserMatchClass = SImmAsmOperand<13, "Lsb0">; 255 let PrintMethod = "printBranchOperand"; 256 let EncoderMethod = "getImmOpValueAsr1"; 257 let DecoderMethod = "decodeSImmOperandAndLsl1<13>"; 258 let MCOperandPredicate = [{ 259 int64_t Imm; 260 if (MCOp.evaluateAsConstantImm(Imm)) 261 return isShiftedInt<12, 1>(Imm); 262 return MCOp.isBareSymbolRef(); 263 }]; 264 let OperandType = "OPERAND_PCREL"; 265} 266 267class UImm20Operand : RISCVOp { 268 let EncoderMethod = "getImmOpValue"; 269 let DecoderMethod = "decodeUImmOperand<20>"; 270 let OperandType = "OPERAND_UIMM20"; 271} 272 273class UImm20OperandMaybeSym : UImm20Operand { 274 let MCOperandPredicate = [{ 275 int64_t Imm; 276 if (MCOp.evaluateAsConstantImm(Imm)) 277 return isUInt<20>(Imm); 278 return MCOp.isBareSymbolRef(); 279 }]; 280} 281 282def uimm20_lui : UImm20OperandMaybeSym { 283 let ParserMatchClass = UImmAsmOperand<20, "LUI">; 284} 285def uimm20_auipc : UImm20OperandMaybeSym { 286 let ParserMatchClass = UImmAsmOperand<20, "AUIPC">; 287} 288 289def uimm20 : UImm20Operand { 290 let ParserMatchClass = UImmAsmOperand<20>; 291 let MCOperandPredicate = [{ 292 int64_t Imm; 293 if (!MCOp.evaluateAsConstantImm(Imm)) 294 return false; 295 return isUInt<20>(Imm); 296 }]; 297} 298 299def Simm21Lsb0JALAsmOperand : SImmAsmOperand<21, "Lsb0JAL"> { 300 let ParserMethod = "parseJALOffset"; 301} 302 303// A 21-bit signed immediate where the least significant bit is zero. 304def simm21_lsb0_jal : Operand<OtherVT> { 305 let ParserMatchClass = Simm21Lsb0JALAsmOperand; 306 let PrintMethod = "printBranchOperand"; 307 let EncoderMethod = "getImmOpValueAsr1"; 308 let DecoderMethod = "decodeSImmOperandAndLsl1<21>"; 309 let MCOperandPredicate = [{ 310 int64_t Imm; 311 if (MCOp.evaluateAsConstantImm(Imm)) 312 return isShiftedInt<20, 1>(Imm); 313 return MCOp.isBareSymbolRef(); 314 }]; 315 let OperandType = "OPERAND_PCREL"; 316} 317 318def BareSymbol : AsmOperandClass { 319 let Name = "BareSymbol"; 320 let RenderMethod = "addImmOperands"; 321 let DiagnosticType = "InvalidBareSymbol"; 322 let ParserMethod = "parseBareSymbol"; 323} 324 325// A bare symbol. 326def bare_symbol : Operand<XLenVT> { 327 let ParserMatchClass = BareSymbol; 328} 329 330def CallSymbol : AsmOperandClass { 331 let Name = "CallSymbol"; 332 let RenderMethod = "addImmOperands"; 333 let DiagnosticType = "InvalidCallSymbol"; 334 let ParserMethod = "parseCallSymbol"; 335} 336 337// A bare symbol used in call/tail only. 338def call_symbol : Operand<XLenVT> { 339 let ParserMatchClass = CallSymbol; 340} 341 342def PseudoJumpSymbol : AsmOperandClass { 343 let Name = "PseudoJumpSymbol"; 344 let RenderMethod = "addImmOperands"; 345 let DiagnosticType = "InvalidPseudoJumpSymbol"; 346 let ParserMethod = "parsePseudoJumpSymbol"; 347} 348 349// A bare symbol used for pseudo jumps only. 350def pseudo_jump_symbol : Operand<XLenVT> { 351 let ParserMatchClass = PseudoJumpSymbol; 352} 353 354def TPRelAddSymbol : AsmOperandClass { 355 let Name = "TPRelAddSymbol"; 356 let RenderMethod = "addImmOperands"; 357 let DiagnosticType = "InvalidTPRelAddSymbol"; 358 let ParserMethod = "parseOperandWithModifier"; 359} 360 361// A bare symbol with the %tprel_add variant. 362def tprel_add_symbol : Operand<XLenVT> { 363 let ParserMatchClass = TPRelAddSymbol; 364} 365 366def CSRSystemRegister : AsmOperandClass { 367 let Name = "CSRSystemRegister"; 368 let ParserMethod = "parseCSRSystemRegister"; 369 let DiagnosticType = "InvalidCSRSystemRegister"; 370} 371 372def csr_sysreg : RISCVOp, TImmLeaf<XLenVT, "return isUInt<12>(Imm);"> { 373 let ParserMatchClass = CSRSystemRegister; 374 let PrintMethod = "printCSRSystemRegister"; 375 let DecoderMethod = "decodeUImmOperand<12>"; 376 let OperandType = "OPERAND_UIMM12"; 377} 378 379// A parameterized register class alternative to i32imm/i64imm from Target.td. 380def ixlenimm : Operand<XLenVT>; 381 382def ixlenimm_li : Operand<XLenVT> { 383 let ParserMatchClass = ImmXLenAsmOperand<"", "LI">; 384} 385 386// Accepts subset of LI operands, used by LAImm and LLAImm 387def ixlenimm_li_restricted : Operand<XLenVT> { 388 let ParserMatchClass = ImmXLenAsmOperand<"", "LI_Restricted">; 389} 390 391// Standalone (codegen-only) immleaf patterns. 392 393// A 6-bit constant greater than 32. 394def uimm6gt32 : ImmLeaf<XLenVT, [{ 395 return isUInt<6>(Imm) && Imm > 32; 396}]>; 397 398// Addressing modes. 399// Necessary because a frameindex can't be matched directly in a pattern. 400def FrameAddrRegImm : ComplexPattern<iPTR, 2, "SelectFrameAddrRegImm", 401 [frameindex, or, add]>; 402def AddrRegImm : ComplexPattern<iPTR, 2, "SelectAddrRegImm">; 403 404// Return the negation of an immediate value. 405def NegImm : SDNodeXForm<imm, [{ 406 return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N), 407 N->getValueType(0)); 408}]>; 409 410// Return an immediate value minus 32. 411def ImmSub32 : SDNodeXForm<imm, [{ 412 return CurDAG->getTargetConstant(N->getSExtValue() - 32, SDLoc(N), 413 N->getValueType(0)); 414}]>; 415 416// Return an immediate subtracted from XLen. 417def ImmSubFromXLen : SDNodeXForm<imm, [{ 418 uint64_t XLen = Subtarget->getXLen(); 419 return CurDAG->getTargetConstant(XLen - N->getZExtValue(), SDLoc(N), 420 N->getValueType(0)); 421}]>; 422 423// Return an immediate subtracted from 32. 424def ImmSubFrom32 : SDNodeXForm<imm, [{ 425 return CurDAG->getTargetConstant(32 - N->getZExtValue(), SDLoc(N), 426 N->getValueType(0)); 427}]>; 428 429// Check if (add r, imm) can be optimized to (ADDI (ADDI r, imm0), imm1), 430// in which imm = imm0 + imm1 and both imm0 and imm1 are simm12. We make imm0 431// as large as possible and imm1 as small as possible so that we might be able 432// to use c.addi for the small immediate. 433def AddiPair : PatLeaf<(imm), [{ 434 if (!N->hasOneUse()) 435 return false; 436 // The immediate operand must be in range [-4096,-2049] or [2048,4094]. 437 int64_t Imm = N->getSExtValue(); 438 return (-4096 <= Imm && Imm <= -2049) || (2048 <= Imm && Imm <= 4094); 439}]>; 440 441// Return imm - (imm < 0 ? -2048 : 2047). 442def AddiPairImmSmall : SDNodeXForm<imm, [{ 443 int64_t Imm = N->getSExtValue(); 444 int64_t Adj = N->getSExtValue() < 0 ? -2048 : 2047; 445 return CurDAG->getTargetConstant(Imm - Adj, SDLoc(N), 446 N->getValueType(0)); 447}]>; 448 449// Return -2048 if immediate is negative or 2047 if positive. These are the 450// largest simm12 values. 451def AddiPairImmLarge : SDNodeXForm<imm, [{ 452 int64_t Imm = N->getSExtValue() < 0 ? -2048 : 2047; 453 return CurDAG->getTargetConstant(Imm, SDLoc(N), 454 N->getValueType(0)); 455}]>; 456 457def TrailingZeros : SDNodeXForm<imm, [{ 458 return CurDAG->getTargetConstant(llvm::countr_zero(N->getZExtValue()), 459 SDLoc(N), N->getValueType(0)); 460}]>; 461 462def XLenSubTrailingOnes : SDNodeXForm<imm, [{ 463 uint64_t XLen = Subtarget->getXLen(); 464 uint64_t TrailingOnes = llvm::countr_one(N->getZExtValue()); 465 return CurDAG->getTargetConstant(XLen - TrailingOnes, SDLoc(N), 466 N->getValueType(0)); 467}]>; 468 469// Checks if this mask is a non-empty sequence of ones starting at the 470// most/least significant bit with the remainder zero and exceeds simm32/simm12. 471def LeadingOnesMask : PatLeaf<(imm), [{ 472 if (!N->hasOneUse()) 473 return false; 474 return !isInt<32>(N->getSExtValue()) && isMask_64(~N->getSExtValue()); 475}], TrailingZeros>; 476 477def TrailingOnesMask : PatLeaf<(imm), [{ 478 if (!N->hasOneUse()) 479 return false; 480 return !isInt<12>(N->getSExtValue()) && isMask_64(N->getZExtValue()); 481}], XLenSubTrailingOnes>; 482 483// Similar to LeadingOnesMask, but only consider leading ones in the lower 32 484// bits. 485def LeadingOnesWMask : PatLeaf<(imm), [{ 486 if (!N->hasOneUse()) 487 return false; 488 // If the value is a uint32 but not an int32, it must have bit 31 set and 489 // bits 63:32 cleared. After that we're looking for a shifted mask but not 490 // an all ones mask. 491 int64_t Imm = N->getSExtValue(); 492 return !isInt<32>(Imm) && isUInt<32>(Imm) && isShiftedMask_64(Imm) && 493 Imm != UINT64_C(0xffffffff); 494}], TrailingZeros>; 495 496//===----------------------------------------------------------------------===// 497// Instruction Formats 498//===----------------------------------------------------------------------===// 499 500include "RISCVInstrFormats.td" 501 502//===----------------------------------------------------------------------===// 503// Instruction Class Templates 504//===----------------------------------------------------------------------===// 505 506let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 507class BranchCC_rri<bits<3> funct3, string opcodestr> 508 : RVInstB<funct3, OPC_BRANCH, (outs), 509 (ins GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12), 510 opcodestr, "$rs1, $rs2, $imm12">, 511 Sched<[WriteJmp, ReadJmp, ReadJmp]> { 512 let isBranch = 1; 513 let isTerminator = 1; 514} 515 516let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { 517class Load_ri<bits<3> funct3, string opcodestr> 518 : RVInstI<funct3, OPC_LOAD, (outs GPR:$rd), (ins GPRMem:$rs1, simm12:$imm12), 519 opcodestr, "$rd, ${imm12}(${rs1})">; 520 521class HLoad_r<bits<7> funct7, bits<5> funct5, string opcodestr> 522 : RVInstR<funct7, 0b100, OPC_SYSTEM, (outs GPR:$rd), 523 (ins GPRMemZeroOffset:$rs1), opcodestr, "$rd, $rs1"> { 524 let rs2 = funct5; 525} 526} 527 528// Operands for stores are in the order srcreg, base, offset rather than 529// reflecting the order these fields are specified in the instruction 530// encoding. 531let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in { 532class Store_rri<bits<3> funct3, string opcodestr> 533 : RVInstS<funct3, OPC_STORE, (outs), 534 (ins GPR:$rs2, GPRMem:$rs1, simm12:$imm12), 535 opcodestr, "$rs2, ${imm12}(${rs1})">; 536 537class HStore_rr<bits<7> funct7, string opcodestr> 538 : RVInstR<funct7, 0b100, OPC_SYSTEM, (outs), 539 (ins GPR:$rs2, GPRMemZeroOffset:$rs1), 540 opcodestr, "$rs2, $rs1"> { 541 let rd = 0; 542} 543} 544 545let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 546class ALU_ri<bits<3> funct3, string opcodestr> 547 : RVInstI<funct3, OPC_OP_IMM, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), 548 opcodestr, "$rd, $rs1, $imm12">, 549 Sched<[WriteIALU, ReadIALU]>; 550 551let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 552class Shift_ri<bits<5> imm11_7, bits<3> funct3, string opcodestr> 553 : RVInstIShift<imm11_7, funct3, OPC_OP_IMM, (outs GPR:$rd), 554 (ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr, 555 "$rd, $rs1, $shamt">, 556 Sched<[WriteShiftImm, ReadShiftImm]>; 557 558let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 559class ALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr, 560 bit Commutable = 0> 561 : RVInstR<funct7, funct3, OPC_OP, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), 562 opcodestr, "$rd, $rs1, $rs2"> { 563 let isCommutable = Commutable; 564} 565 566let hasNoSchedulingInfo = 1, 567 hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 568class CSR_ir<bits<3> funct3, string opcodestr> 569 : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), (ins csr_sysreg:$imm12, GPR:$rs1), 570 opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR, ReadCSR]>; 571 572let hasNoSchedulingInfo = 1, 573 hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 574class CSR_ii<bits<3> funct3, string opcodestr> 575 : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), 576 (ins csr_sysreg:$imm12, uimm5:$rs1), 577 opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR]>; 578 579let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 580class ShiftW_ri<bits<7> imm11_5, bits<3> funct3, string opcodestr> 581 : RVInstIShiftW<imm11_5, funct3, OPC_OP_IMM_32, (outs GPR:$rd), 582 (ins GPR:$rs1, uimm5:$shamt), opcodestr, 583 "$rd, $rs1, $shamt">, 584 Sched<[WriteShiftImm32, ReadShiftImm32]>; 585 586let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 587class ALUW_rr<bits<7> funct7, bits<3> funct3, string opcodestr, 588 bit Commutable = 0> 589 : RVInstR<funct7, funct3, OPC_OP_32, (outs GPR:$rd), 590 (ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2"> { 591 let isCommutable = Commutable; 592} 593 594let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 595class Priv<string opcodestr, bits<7> funct7> 596 : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2), 597 opcodestr, "">; 598 599let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 600class Priv_rr<string opcodestr, bits<7> funct7> 601 : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2), 602 opcodestr, "$rs1, $rs2"> { 603 let rd = 0; 604} 605 606//===----------------------------------------------------------------------===// 607// Instructions 608//===----------------------------------------------------------------------===// 609 610let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { 611let isReMaterializable = 1, isAsCheapAsAMove = 1, 612 IsSignExtendingOpW = 1 in 613def LUI : RVInstU<OPC_LUI, (outs GPR:$rd), (ins uimm20_lui:$imm20), 614 "lui", "$rd, $imm20">, Sched<[WriteIALU]>; 615 616def AUIPC : RVInstU<OPC_AUIPC, (outs GPR:$rd), (ins uimm20_auipc:$imm20), 617 "auipc", "$rd, $imm20">, Sched<[WriteIALU]>; 618 619def JAL : RVInstJ<OPC_JAL, (outs GPR:$rd), (ins simm21_lsb0_jal:$imm20), 620 "jal", "$rd, $imm20">, Sched<[WriteJal]>; 621 622def JALR : RVInstI<0b000, OPC_JALR, (outs GPR:$rd), 623 (ins GPR:$rs1, simm12:$imm12), 624 "jalr", "$rd, ${imm12}(${rs1})">, 625 Sched<[WriteJalr, ReadJalr]>; 626} // hasSideEffects = 0, mayLoad = 0, mayStore = 0 627 628def BEQ : BranchCC_rri<0b000, "beq">; 629def BNE : BranchCC_rri<0b001, "bne">; 630def BLT : BranchCC_rri<0b100, "blt">; 631def BGE : BranchCC_rri<0b101, "bge">; 632def BLTU : BranchCC_rri<0b110, "bltu">; 633def BGEU : BranchCC_rri<0b111, "bgeu">; 634 635let IsSignExtendingOpW = 1 in { 636def LB : Load_ri<0b000, "lb">, Sched<[WriteLDB, ReadMemBase]>; 637def LH : Load_ri<0b001, "lh">, Sched<[WriteLDH, ReadMemBase]>; 638def LW : Load_ri<0b010, "lw">, Sched<[WriteLDW, ReadMemBase]>; 639def LBU : Load_ri<0b100, "lbu">, Sched<[WriteLDB, ReadMemBase]>; 640def LHU : Load_ri<0b101, "lhu">, Sched<[WriteLDH, ReadMemBase]>; 641} 642 643def SB : Store_rri<0b000, "sb">, Sched<[WriteSTB, ReadStoreData, ReadMemBase]>; 644def SH : Store_rri<0b001, "sh">, Sched<[WriteSTH, ReadStoreData, ReadMemBase]>; 645def SW : Store_rri<0b010, "sw">, Sched<[WriteSTW, ReadStoreData, ReadMemBase]>; 646 647// ADDI isn't always rematerializable, but isReMaterializable will be used as 648// a hint which is verified in isReallyTriviallyReMaterializable. 649let isReMaterializable = 1, isAsCheapAsAMove = 1 in 650def ADDI : ALU_ri<0b000, "addi">; 651 652let IsSignExtendingOpW = 1 in { 653def SLTI : ALU_ri<0b010, "slti">; 654def SLTIU : ALU_ri<0b011, "sltiu">; 655} 656 657let isReMaterializable = 1, isAsCheapAsAMove = 1 in { 658def XORI : ALU_ri<0b100, "xori">; 659def ORI : ALU_ri<0b110, "ori">; 660} 661 662def ANDI : ALU_ri<0b111, "andi">; 663 664def SLLI : Shift_ri<0b00000, 0b001, "slli">; 665def SRLI : Shift_ri<0b00000, 0b101, "srli">; 666def SRAI : Shift_ri<0b01000, 0b101, "srai">; 667 668def ADD : ALU_rr<0b0000000, 0b000, "add", Commutable=1>, 669 Sched<[WriteIALU, ReadIALU, ReadIALU]>; 670def SUB : ALU_rr<0b0100000, 0b000, "sub">, 671 Sched<[WriteIALU, ReadIALU, ReadIALU]>; 672def SLL : ALU_rr<0b0000000, 0b001, "sll">, 673 Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; 674let IsSignExtendingOpW = 1 in { 675def SLT : ALU_rr<0b0000000, 0b010, "slt">, 676 Sched<[WriteIALU, ReadIALU, ReadIALU]>; 677def SLTU : ALU_rr<0b0000000, 0b011, "sltu">, 678 Sched<[WriteIALU, ReadIALU, ReadIALU]>; 679} 680def XOR : ALU_rr<0b0000000, 0b100, "xor", Commutable=1>, 681 Sched<[WriteIALU, ReadIALU, ReadIALU]>; 682def SRL : ALU_rr<0b0000000, 0b101, "srl">, 683 Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; 684def SRA : ALU_rr<0b0100000, 0b101, "sra">, 685 Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; 686def OR : ALU_rr<0b0000000, 0b110, "or", Commutable=1>, 687 Sched<[WriteIALU, ReadIALU, ReadIALU]>; 688def AND : ALU_rr<0b0000000, 0b111, "and", Commutable=1>, 689 Sched<[WriteIALU, ReadIALU, ReadIALU]>; 690 691let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in { 692def FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs), 693 (ins fencearg:$pred, fencearg:$succ), 694 "fence", "$pred, $succ">, Sched<[]> { 695 bits<4> pred; 696 bits<4> succ; 697 698 let rs1 = 0; 699 let rd = 0; 700 let imm12 = {0b0000,pred,succ}; 701} 702 703def FENCE_TSO : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins), "fence.tso", "">, Sched<[]> { 704 let rs1 = 0; 705 let rd = 0; 706 let imm12 = {0b1000,0b0011,0b0011}; 707} 708 709def FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), "fence.i", "">, Sched<[]> { 710 let rs1 = 0; 711 let rd = 0; 712 let imm12 = 0; 713} 714 715def ECALL : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ecall", "">, Sched<[WriteJmp]> { 716 let rs1 = 0; 717 let rd = 0; 718 let imm12 = 0; 719} 720 721def EBREAK : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ebreak", "">, 722 Sched<[]> { 723 let rs1 = 0; 724 let rd = 0; 725 let imm12 = 1; 726} 727 728// This is a de facto standard (as set by GNU binutils) 32-bit unimplemented 729// instruction (i.e., it should always trap, if your implementation has invalid 730// instruction traps). 731def UNIMP : RVInstI<0b001, OPC_SYSTEM, (outs), (ins), "unimp", "">, 732 Sched<[]> { 733 let rs1 = 0; 734 let rd = 0; 735 let imm12 = 0b110000000000; 736} 737 738} // hasSideEffects = 1, mayLoad = 0, mayStore = 0 739 740def CSRRW : CSR_ir<0b001, "csrrw">; 741def CSRRS : CSR_ir<0b010, "csrrs">; 742def CSRRC : CSR_ir<0b011, "csrrc">; 743 744def CSRRWI : CSR_ii<0b101, "csrrwi">; 745def CSRRSI : CSR_ii<0b110, "csrrsi">; 746def CSRRCI : CSR_ii<0b111, "csrrci">; 747 748/// RV64I instructions 749 750let Predicates = [IsRV64] in { 751def LWU : Load_ri<0b110, "lwu">, Sched<[WriteLDW, ReadMemBase]>; 752def LD : Load_ri<0b011, "ld">, Sched<[WriteLDD, ReadMemBase]>; 753def SD : Store_rri<0b011, "sd">, Sched<[WriteSTD, ReadStoreData, ReadMemBase]>; 754 755let IsSignExtendingOpW = 1 in { 756let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 757def ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd), 758 (ins GPR:$rs1, simm12:$imm12), 759 "addiw", "$rd, $rs1, $imm12">, 760 Sched<[WriteIALU32, ReadIALU32]>; 761 762def SLLIW : ShiftW_ri<0b0000000, 0b001, "slliw">; 763def SRLIW : ShiftW_ri<0b0000000, 0b101, "srliw">; 764def SRAIW : ShiftW_ri<0b0100000, 0b101, "sraiw">; 765 766def ADDW : ALUW_rr<0b0000000, 0b000, "addw", Commutable=1>, 767 Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; 768def SUBW : ALUW_rr<0b0100000, 0b000, "subw">, 769 Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; 770def SLLW : ALUW_rr<0b0000000, 0b001, "sllw">, 771 Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; 772def SRLW : ALUW_rr<0b0000000, 0b101, "srlw">, 773 Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; 774def SRAW : ALUW_rr<0b0100000, 0b101, "sraw">, 775 Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; 776} // IsSignExtendingOpW = 1 777} // Predicates = [IsRV64] 778 779//===----------------------------------------------------------------------===// 780// Privileged instructions 781//===----------------------------------------------------------------------===// 782 783let isBarrier = 1, isReturn = 1, isTerminator = 1 in { 784def SRET : Priv<"sret", 0b0001000>, Sched<[]> { 785 let rd = 0; 786 let rs1 = 0; 787 let rs2 = 0b00010; 788} 789 790def MRET : Priv<"mret", 0b0011000>, Sched<[]> { 791 let rd = 0; 792 let rs1 = 0; 793 let rs2 = 0b00010; 794} 795} // isBarrier = 1, isReturn = 1, isTerminator = 1 796 797def WFI : Priv<"wfi", 0b0001000>, Sched<[]> { 798 let rd = 0; 799 let rs1 = 0; 800 let rs2 = 0b00101; 801} 802 803let Predicates = [HasStdExtSvinval] in { 804def SFENCE_W_INVAL : Priv<"sfence.w.inval", 0b0001100>, Sched<[]> { 805 let rd = 0; 806 let rs1 = 0; 807 let rs2 = 0; 808} 809 810def SFENCE_INVAL_IR : Priv<"sfence.inval.ir", 0b0001100>, Sched<[]> { 811 let rd = 0; 812 let rs1 = 0; 813 let rs2 = 0b00001; 814} 815def SINVAL_VMA : Priv_rr<"sinval.vma", 0b0001011>, Sched<[]>; 816def HINVAL_VVMA : Priv_rr<"hinval.vvma", 0b0010011>, Sched<[]>; 817def HINVAL_GVMA : Priv_rr<"hinval.gvma", 0b0110011>, Sched<[]>; 818} // Predicates = [HasStdExtSvinval] 819 820def SFENCE_VMA : Priv_rr<"sfence.vma", 0b0001001>, Sched<[]>; 821 822let Predicates = [HasStdExtH] in { 823def HFENCE_VVMA : Priv_rr<"hfence.vvma", 0b0010001>, Sched<[]>; 824def HFENCE_GVMA : Priv_rr<"hfence.gvma", 0b0110001>, Sched<[]>; 825 826def HLV_B : HLoad_r<0b0110000, 0b00000, "hlv.b">, Sched<[]>; 827def HLV_BU : HLoad_r<0b0110000, 0b00001, "hlv.bu">, Sched<[]>; 828def HLV_H : HLoad_r<0b0110010, 0b00000, "hlv.h">, Sched<[]>; 829def HLV_HU : HLoad_r<0b0110010, 0b00001, "hlv.hu">, Sched<[]>; 830def HLVX_HU : HLoad_r<0b0110010, 0b00011, "hlvx.hu">, Sched<[]>; 831def HLV_W : HLoad_r<0b0110100, 0b00000, "hlv.w">, Sched<[]>; 832def HLVX_WU : HLoad_r<0b0110100, 0b00011, "hlvx.wu">, Sched<[]>; 833def HSV_B : HStore_rr<0b0110001, "hsv.b">, Sched<[]>; 834def HSV_H : HStore_rr<0b0110011, "hsv.h">, Sched<[]>; 835def HSV_W : HStore_rr<0b0110101, "hsv.w">, Sched<[]>; 836} 837let Predicates = [IsRV64, HasStdExtH] in { 838def HLV_WU : HLoad_r<0b0110100, 0b00001, "hlv.wu">, Sched<[]>; 839def HLV_D : HLoad_r<0b0110110, 0b00000, "hlv.d">, Sched<[]>; 840def HSV_D : HStore_rr<0b0110111, "hsv.d">, Sched<[]>; 841} 842 843//===----------------------------------------------------------------------===// 844// Debug instructions 845//===----------------------------------------------------------------------===// 846 847let isBarrier = 1, isReturn = 1, isTerminator = 1 in { 848def DRET : Priv<"dret", 0b0111101>, Sched<[]> { 849 let rd = 0; 850 let rs1 = 0; 851 let rs2 = 0b10010; 852} 853} // isBarrier = 1, isReturn = 1, isTerminator = 1 854 855//===----------------------------------------------------------------------===// 856// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20) 857//===----------------------------------------------------------------------===// 858 859def : InstAlias<"nop", (ADDI X0, X0, 0)>; 860 861// Note that the size is 32 because up to 8 32-bit instructions are needed to 862// generate an arbitrary 64-bit immediate. However, the size does not really 863// matter since PseudoLI is currently only used in the AsmParser where it gets 864// expanded to real instructions immediately. 865let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32, 866 isCodeGenOnly = 0, isAsmParserOnly = 1 in 867def PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm_li:$imm), [], 868 "li", "$rd, $imm">; 869 870def PseudoLB : PseudoLoad<"lb">; 871def PseudoLBU : PseudoLoad<"lbu">; 872def PseudoLH : PseudoLoad<"lh">; 873def PseudoLHU : PseudoLoad<"lhu">; 874def PseudoLW : PseudoLoad<"lw">; 875 876def PseudoSB : PseudoStore<"sb">; 877def PseudoSH : PseudoStore<"sh">; 878def PseudoSW : PseudoStore<"sw">; 879 880let Predicates = [IsRV64] in { 881def PseudoLWU : PseudoLoad<"lwu">; 882def PseudoLD : PseudoLoad<"ld">; 883def PseudoSD : PseudoStore<"sd">; 884} // Predicates = [IsRV64] 885 886def : InstAlias<"li $rd, $imm", (ADDI GPR:$rd, X0, simm12:$imm)>; 887def : InstAlias<"mv $rd, $rs", (ADDI GPR:$rd, GPR:$rs, 0)>; 888def : InstAlias<"not $rd, $rs", (XORI GPR:$rd, GPR:$rs, -1)>; 889def : InstAlias<"neg $rd, $rs", (SUB GPR:$rd, X0, GPR:$rs)>; 890 891let Predicates = [IsRV64] in { 892def : InstAlias<"negw $rd, $rs", (SUBW GPR:$rd, X0, GPR:$rs)>; 893def : InstAlias<"sext.w $rd, $rs", (ADDIW GPR:$rd, GPR:$rs, 0)>; 894} // Predicates = [IsRV64] 895 896def : InstAlias<"seqz $rd, $rs", (SLTIU GPR:$rd, GPR:$rs, 1)>; 897def : InstAlias<"snez $rd, $rs", (SLTU GPR:$rd, X0, GPR:$rs)>; 898def : InstAlias<"sltz $rd, $rs", (SLT GPR:$rd, GPR:$rs, X0)>; 899def : InstAlias<"sgtz $rd, $rs", (SLT GPR:$rd, X0, GPR:$rs)>; 900 901// sgt/sgtu are recognised by the GNU assembler but the canonical slt/sltu 902// form will always be printed. Therefore, set a zero weight. 903def : InstAlias<"sgt $rd, $rs, $rt", (SLT GPR:$rd, GPR:$rt, GPR:$rs), 0>; 904def : InstAlias<"sgtu $rd, $rs, $rt", (SLTU GPR:$rd, GPR:$rt, GPR:$rs), 0>; 905 906def : InstAlias<"beqz $rs, $offset", 907 (BEQ GPR:$rs, X0, simm13_lsb0:$offset)>; 908def : InstAlias<"bnez $rs, $offset", 909 (BNE GPR:$rs, X0, simm13_lsb0:$offset)>; 910def : InstAlias<"blez $rs, $offset", 911 (BGE X0, GPR:$rs, simm13_lsb0:$offset)>; 912def : InstAlias<"bgez $rs, $offset", 913 (BGE GPR:$rs, X0, simm13_lsb0:$offset)>; 914def : InstAlias<"bltz $rs, $offset", 915 (BLT GPR:$rs, X0, simm13_lsb0:$offset)>; 916def : InstAlias<"bgtz $rs, $offset", 917 (BLT X0, GPR:$rs, simm13_lsb0:$offset)>; 918 919// Always output the canonical mnemonic for the pseudo branch instructions. 920// The GNU tools emit the canonical mnemonic for the branch pseudo instructions 921// as well (e.g. "bgt" will be recognised by the assembler but never printed by 922// objdump). Match this behaviour by setting a zero weight. 923def : InstAlias<"bgt $rs, $rt, $offset", 924 (BLT GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 925def : InstAlias<"ble $rs, $rt, $offset", 926 (BGE GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 927def : InstAlias<"bgtu $rs, $rt, $offset", 928 (BLTU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 929def : InstAlias<"bleu $rs, $rt, $offset", 930 (BGEU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 931 932def : InstAlias<"j $offset", (JAL X0, simm21_lsb0_jal:$offset)>; 933def : InstAlias<"jal $offset", (JAL X1, simm21_lsb0_jal:$offset)>; 934 935// Non-zero offset aliases of "jalr" are the lowest weight, followed by the 936// two-register form, then the one-register forms and finally "ret". 937def : InstAlias<"jr $rs", (JALR X0, GPR:$rs, 0), 3>; 938def : InstAlias<"jr ${offset}(${rs})", (JALR X0, GPR:$rs, simm12:$offset)>; 939def : InstAlias<"jalr $rs", (JALR X1, GPR:$rs, 0), 3>; 940def : InstAlias<"jalr ${offset}(${rs})", (JALR X1, GPR:$rs, simm12:$offset)>; 941def : InstAlias<"jalr $rd, $rs", (JALR GPR:$rd, GPR:$rs, 0), 2>; 942def : InstAlias<"ret", (JALR X0, X1, 0), 4>; 943 944// Non-canonical forms for jump targets also accepted by the assembler. 945def : InstAlias<"jr $rs, $offset", (JALR X0, GPR:$rs, simm12:$offset), 0>; 946def : InstAlias<"jalr $rs, $offset", (JALR X1, GPR:$rs, simm12:$offset), 0>; 947def : InstAlias<"jalr $rd, $rs, $offset", (JALR GPR:$rd, GPR:$rs, simm12:$offset), 0>; 948def : InstAlias<"jr (${rs})", (JALR X0, GPR:$rs, 0), 0>; 949def : InstAlias<"jalr (${rs})", (JALR X1, GPR:$rs, 0), 0>; 950def : InstAlias<"jalr $rd, (${rs})", (JALR GPR:$rd, GPR:$rs, 0), 0>; 951 952def : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw 953 954let Predicates = [HasStdExtZihintpause] in 955def : InstAlias<"pause", (FENCE 0x1, 0x0)>; // 0x1 == w 956 957def : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, INSTRET.Encoding, X0)>; 958def : InstAlias<"rdcycle $rd", (CSRRS GPR:$rd, CYCLE.Encoding, X0)>; 959def : InstAlias<"rdtime $rd", (CSRRS GPR:$rd, TIME.Encoding, X0)>; 960 961let Predicates = [IsRV32] in { 962def : InstAlias<"rdinstreth $rd", (CSRRS GPR:$rd, INSTRETH.Encoding, X0)>; 963def : InstAlias<"rdcycleh $rd", (CSRRS GPR:$rd, CYCLEH.Encoding, X0)>; 964def : InstAlias<"rdtimeh $rd", (CSRRS GPR:$rd, TIMEH.Encoding, X0)>; 965} // Predicates = [IsRV32] 966 967def : InstAlias<"csrr $rd, $csr", (CSRRS GPR:$rd, csr_sysreg:$csr, X0)>; 968def : InstAlias<"csrw $csr, $rs", (CSRRW X0, csr_sysreg:$csr, GPR:$rs)>; 969def : InstAlias<"csrs $csr, $rs", (CSRRS X0, csr_sysreg:$csr, GPR:$rs)>; 970def : InstAlias<"csrc $csr, $rs", (CSRRC X0, csr_sysreg:$csr, GPR:$rs)>; 971 972def : InstAlias<"csrwi $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>; 973def : InstAlias<"csrsi $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>; 974def : InstAlias<"csrci $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>; 975 976let EmitPriority = 0 in { 977def : InstAlias<"csrw $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>; 978def : InstAlias<"csrs $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>; 979def : InstAlias<"csrc $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>; 980 981def : InstAlias<"csrrw $rd, $csr, $imm", (CSRRWI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 982def : InstAlias<"csrrs $rd, $csr, $imm", (CSRRSI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 983def : InstAlias<"csrrc $rd, $csr, $imm", (CSRRCI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 984} 985 986def : InstAlias<"sfence.vma", (SFENCE_VMA X0, X0)>; 987def : InstAlias<"sfence.vma $rs", (SFENCE_VMA GPR:$rs, X0)>; 988 989def : InstAlias<"hfence.gvma", (HFENCE_GVMA X0, X0)>; 990def : InstAlias<"hfence.gvma $rs", (HFENCE_GVMA GPR:$rs, X0)>; 991 992def : InstAlias<"hfence.vvma", (HFENCE_VVMA X0, X0)>; 993def : InstAlias<"hfence.vvma $rs", (HFENCE_VVMA GPR:$rs, X0)>; 994 995let Predicates = [HasStdExtZihintntl] in { 996 def : InstAlias<"ntl.p1", (ADD X0, X0, X2)>; 997 def : InstAlias<"ntl.pall", (ADD X0, X0, X3)>; 998 def : InstAlias<"ntl.s1", (ADD X0, X0, X4)>; 999 def : InstAlias<"ntl.all", (ADD X0, X0, X5)>; 1000} // Predicates = [HasStdExtZihintntl] 1001 1002let EmitPriority = 0 in { 1003def : InstAlias<"lb $rd, (${rs1})", 1004 (LB GPR:$rd, GPR:$rs1, 0)>; 1005def : InstAlias<"lh $rd, (${rs1})", 1006 (LH GPR:$rd, GPR:$rs1, 0)>; 1007def : InstAlias<"lw $rd, (${rs1})", 1008 (LW GPR:$rd, GPR:$rs1, 0)>; 1009def : InstAlias<"lbu $rd, (${rs1})", 1010 (LBU GPR:$rd, GPR:$rs1, 0)>; 1011def : InstAlias<"lhu $rd, (${rs1})", 1012 (LHU GPR:$rd, GPR:$rs1, 0)>; 1013 1014def : InstAlias<"sb $rs2, (${rs1})", 1015 (SB GPR:$rs2, GPR:$rs1, 0)>; 1016def : InstAlias<"sh $rs2, (${rs1})", 1017 (SH GPR:$rs2, GPR:$rs1, 0)>; 1018def : InstAlias<"sw $rs2, (${rs1})", 1019 (SW GPR:$rs2, GPR:$rs1, 0)>; 1020 1021def : InstAlias<"add $rd, $rs1, $imm12", 1022 (ADDI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 1023def : InstAlias<"and $rd, $rs1, $imm12", 1024 (ANDI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 1025def : InstAlias<"xor $rd, $rs1, $imm12", 1026 (XORI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 1027def : InstAlias<"or $rd, $rs1, $imm12", 1028 (ORI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 1029def : InstAlias<"sll $rd, $rs1, $shamt", 1030 (SLLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 1031def : InstAlias<"srl $rd, $rs1, $shamt", 1032 (SRLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 1033def : InstAlias<"sra $rd, $rs1, $shamt", 1034 (SRAI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 1035let Predicates = [IsRV64] in { 1036def : InstAlias<"lwu $rd, (${rs1})", 1037 (LWU GPR:$rd, GPR:$rs1, 0)>; 1038def : InstAlias<"ld $rd, (${rs1})", 1039 (LD GPR:$rd, GPR:$rs1, 0)>; 1040def : InstAlias<"sd $rs2, (${rs1})", 1041 (SD GPR:$rs2, GPR:$rs1, 0)>; 1042 1043def : InstAlias<"addw $rd, $rs1, $imm12", 1044 (ADDIW GPR:$rd, GPR:$rs1, simm12:$imm12)>; 1045def : InstAlias<"sllw $rd, $rs1, $shamt", 1046 (SLLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 1047def : InstAlias<"srlw $rd, $rs1, $shamt", 1048 (SRLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 1049def : InstAlias<"sraw $rd, $rs1, $shamt", 1050 (SRAIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 1051} // Predicates = [IsRV64] 1052def : InstAlias<"slt $rd, $rs1, $imm12", 1053 (SLTI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 1054def : InstAlias<"sltu $rd, $rs1, $imm12", 1055 (SLTIU GPR:$rd, GPR:$rs1, simm12:$imm12)>; 1056} 1057 1058def : MnemonicAlias<"move", "mv">; 1059 1060// The SCALL and SBREAK instructions wererenamed to ECALL and EBREAK in 1061// version 2.1 of the user-level ISA. Like the GNU toolchain, we still accept 1062// the old name for backwards compatibility. 1063def : MnemonicAlias<"scall", "ecall">; 1064def : MnemonicAlias<"sbreak", "ebreak">; 1065 1066// This alias was added to the spec in December 2020. Don't print it by default 1067// to allow assembly we print to be compatible with versions of GNU assembler 1068// that don't support this alias. 1069def : InstAlias<"zext.b $rd, $rs", (ANDI GPR:$rd, GPR:$rs, 0xFF), 0>; 1070 1071let Predicates = [HasStdExtZicfilp] in { 1072def : InstAlias<"lpad $imm20", (AUIPC X0, uimm20:$imm20)>; 1073} 1074 1075//===----------------------------------------------------------------------===// 1076// .insn directive instructions 1077//===----------------------------------------------------------------------===// 1078 1079def AnyRegOperand : AsmOperandClass { 1080 let Name = "AnyRegOperand"; 1081 let RenderMethod = "addRegOperands"; 1082 let PredicateMethod = "isAnyReg"; 1083} 1084 1085def AnyReg : Operand<XLenVT> { 1086 let OperandType = "OPERAND_REGISTER"; 1087 let ParserMatchClass = AnyRegOperand; 1088} 1089 1090// isCodeGenOnly = 1 to hide them from the tablegened assembly parser. 1091let isCodeGenOnly = 1, hasSideEffects = 1, mayLoad = 1, mayStore = 1, 1092 hasNoSchedulingInfo = 1 in { 1093def InsnR : DirectiveInsnR<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$funct3, 1094 uimm7:$funct7, AnyReg:$rs1, 1095 AnyReg:$rs2), 1096 "$opcode, $funct3, $funct7, $rd, $rs1, $rs2">; 1097def InsnR4 : DirectiveInsnR4<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 1098 uimm3:$funct3, 1099 uimm2:$funct2, 1100 AnyReg:$rs1, AnyReg:$rs2, 1101 AnyReg:$rs3), 1102 "$opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3">; 1103def InsnI : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$funct3, 1104 AnyReg:$rs1, simm12:$imm12), 1105 "$opcode, $funct3, $rd, $rs1, $imm12">; 1106def InsnI_Mem : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 1107 uimm3:$funct3, 1108 AnyReg:$rs1, 1109 simm12:$imm12), 1110 "$opcode, $funct3, $rd, ${imm12}(${rs1})">; 1111def InsnB : DirectiveInsnB<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3, 1112 AnyReg:$rs1, AnyReg:$rs2, 1113 simm13_lsb0:$imm12), 1114 "$opcode, $funct3, $rs1, $rs2, $imm12">; 1115def InsnU : DirectiveInsnU<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 1116 uimm20_lui:$imm20), 1117 "$opcode, $rd, $imm20">; 1118def InsnJ : DirectiveInsnJ<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 1119 simm21_lsb0_jal:$imm20), 1120 "$opcode, $rd, $imm20">; 1121def InsnS : DirectiveInsnS<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3, 1122 AnyReg:$rs2, AnyReg:$rs1, 1123 simm12:$imm12), 1124 "$opcode, $funct3, $rs2, ${imm12}(${rs1})">; 1125def Insn32 : RVInst<(outs), (ins uimm32:$value), "", "", [], InstFormatOther> { 1126 bits<32> value; 1127 1128 let Inst{31-0} = value; 1129 let AsmString = ".insn 0x4, $value"; 1130} 1131} 1132 1133// Use InstAliases to match these so that we can combine the insn and format 1134// into a mnemonic to use as the key for the tablegened asm matcher table. The 1135// parser will take care of creating these fake mnemonics and will only do it 1136// for known formats. 1137let EmitPriority = 0 in { 1138def : InstAlias<".insn_r $opcode, $funct3, $funct7, $rd, $rs1, $rs2", 1139 (InsnR AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm7:$funct7, 1140 AnyReg:$rs1, AnyReg:$rs2)>; 1141// Accept 4 register form of ".insn r" as alias for ".insn r4". 1142def : InstAlias<".insn_r $opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3", 1143 (InsnR4 AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm2:$funct2, 1144 AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>; 1145def : InstAlias<".insn_r4 $opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3", 1146 (InsnR4 AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm2:$funct2, 1147 AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>; 1148def : InstAlias<".insn_i $opcode, $funct3, $rd, $rs1, $imm12", 1149 (InsnI AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1, 1150 simm12:$imm12)>; 1151def : InstAlias<".insn_i $opcode, $funct3, $rd, ${imm12}(${rs1})", 1152 (InsnI_Mem AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, 1153 AnyReg:$rs1, simm12:$imm12)>; 1154def : InstAlias<".insn_i $opcode, $funct3, $rd, (${rs1})", 1155 (InsnI_Mem AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, 1156 AnyReg:$rs1, 0)>; 1157def : InstAlias<".insn_b $opcode, $funct3, $rs1, $rs2, $imm12", 1158 (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1, 1159 AnyReg:$rs2, simm13_lsb0:$imm12)>; 1160// Accept sb as an alias for b. 1161def : InstAlias<".insn_sb $opcode, $funct3, $rs1, $rs2, $imm12", 1162 (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1, 1163 AnyReg:$rs2, simm13_lsb0:$imm12)>; 1164def : InstAlias<".insn_u $opcode, $rd, $imm20", 1165 (InsnU AnyReg:$rd, uimm7_opcode:$opcode, uimm20_lui:$imm20)>; 1166def : InstAlias<".insn_j $opcode, $rd, $imm20", 1167 (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>; 1168// Accept uj as an alias for j. 1169def : InstAlias<".insn_uj $opcode, $rd, $imm20", 1170 (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>; 1171def : InstAlias<".insn_s $opcode, $funct3, $rs2, ${imm12}(${rs1})", 1172 (InsnS uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs2, 1173 AnyReg:$rs1, simm12:$imm12)>; 1174def : InstAlias<".insn_s $opcode, $funct3, $rs2, (${rs1})", 1175 (InsnS uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs2, 1176 AnyReg:$rs1, 0)>; 1177} 1178 1179//===----------------------------------------------------------------------===// 1180// Pseudo-instructions and codegen patterns 1181// 1182// Naming convention: For 'generic' pattern classes, we use the naming 1183// convention PatTy1Ty2. For pattern classes which offer a more complex 1184// expansion, prefix the class name, e.g. BccPat. 1185//===----------------------------------------------------------------------===// 1186 1187/// Generic pattern classes 1188 1189class PatGpr<SDPatternOperator OpNode, RVInst Inst, ValueType vt = XLenVT> 1190 : Pat<(vt (OpNode (vt GPR:$rs1))), (Inst GPR:$rs1)>; 1191class PatGprGpr<SDPatternOperator OpNode, RVInst Inst, ValueType vt1 = XLenVT, 1192 ValueType vt2 = XLenVT> 1193 : Pat<(vt1 (OpNode (vt1 GPR:$rs1), (vt2 GPR:$rs2))), (Inst GPR:$rs1, GPR:$rs2)>; 1194 1195class PatGprImm<SDPatternOperator OpNode, RVInst Inst, ImmLeaf ImmType, 1196 ValueType vt = XLenVT> 1197 : Pat<(vt (OpNode (vt GPR:$rs1), ImmType:$imm)), 1198 (Inst GPR:$rs1, ImmType:$imm)>; 1199class PatGprSimm12<SDPatternOperator OpNode, RVInstI Inst> 1200 : PatGprImm<OpNode, Inst, simm12>; 1201class PatGprUimmLog2XLen<SDPatternOperator OpNode, RVInstIShift Inst> 1202 : PatGprImm<OpNode, Inst, uimmlog2xlen>; 1203 1204/// Predicates 1205 1206def assertsexti32 : PatFrag<(ops node:$src), (assertsext node:$src), [{ 1207 return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32); 1208}]>; 1209def sexti16 : ComplexPattern<XLenVT, 1, "selectSExtBits<16>">; 1210def sexti16i32 : ComplexPattern<i32, 1, "selectSExtBits<16>">; 1211def sexti32 : ComplexPattern<i64, 1, "selectSExtBits<32>">; 1212def assertzexti32 : PatFrag<(ops node:$src), (assertzext node:$src), [{ 1213 return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32); 1214}]>; 1215def zexti32 : ComplexPattern<i64, 1, "selectZExtBits<32>">; 1216def zexti16 : ComplexPattern<XLenVT, 1, "selectZExtBits<16>">; 1217def zexti16i32 : ComplexPattern<i32, 1, "selectZExtBits<16>">; 1218def zexti8 : ComplexPattern<XLenVT, 1, "selectZExtBits<8>">; 1219def zexti8i32 : ComplexPattern<i32, 1, "selectZExtBits<8>">; 1220 1221def ext : PatFrags<(ops node:$A), [(sext node:$A), (zext node:$A)]>; 1222 1223class binop_oneuse<SDPatternOperator operator> 1224 : PatFrag<(ops node:$A, node:$B), 1225 (operator node:$A, node:$B), [{ 1226 return N->hasOneUse(); 1227}]>; 1228 1229def and_oneuse : binop_oneuse<and>; 1230def mul_oneuse : binop_oneuse<mul>; 1231 1232def mul_const_oneuse : PatFrag<(ops node:$A, node:$B), 1233 (mul node:$A, node:$B), [{ 1234 if (auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1))) 1235 return N1C->hasOneUse(); 1236 return false; 1237}]>; 1238 1239class unop_oneuse<SDPatternOperator operator> 1240 : PatFrag<(ops node:$A), 1241 (operator node:$A), [{ 1242 return N->hasOneUse(); 1243}]>; 1244 1245def sext_oneuse : unop_oneuse<sext>; 1246def zext_oneuse : unop_oneuse<zext>; 1247def anyext_oneuse : unop_oneuse<anyext>; 1248def ext_oneuse : unop_oneuse<ext>; 1249def fpext_oneuse : unop_oneuse<any_fpextend>; 1250 1251def 33signbits_node : PatLeaf<(i64 GPR:$src), [{ 1252 return CurDAG->ComputeNumSignBits(SDValue(N, 0)) > 32; 1253}]>; 1254 1255/// Simple arithmetic operations 1256 1257def : PatGprGpr<add, ADD>; 1258def : PatGprSimm12<add, ADDI>; 1259def : PatGprGpr<sub, SUB>; 1260def : PatGprGpr<or, OR>; 1261def : PatGprSimm12<or, ORI>; 1262def : PatGprGpr<and, AND>; 1263def : PatGprSimm12<and, ANDI>; 1264def : PatGprGpr<xor, XOR>; 1265def : PatGprSimm12<xor, XORI>; 1266def : PatGprUimmLog2XLen<shl, SLLI>; 1267def : PatGprUimmLog2XLen<srl, SRLI>; 1268def : PatGprUimmLog2XLen<sra, SRAI>; 1269 1270// Select 'or' as ADDI if the immediate bits are known to be 0 in $rs1. This 1271// can improve compressibility. 1272def or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{ 1273 if (N->getFlags().hasDisjoint()) 1274 return true; 1275 KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0); 1276 KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0); 1277 return KnownBits::haveNoCommonBitsSet(Known0, Known1); 1278}]>; 1279def : PatGprSimm12<or_is_add, ADDI>; 1280 1281def add_like : PatFrags<(ops node:$lhs, node:$rhs), 1282 [(or_is_add node:$lhs, node:$rhs), 1283 (add node:$lhs, node:$rhs)]>; 1284 1285// negate of low bit can be done via two (compressible) shifts. The negate 1286// is never compressible since rs1 and rd can't be the same register. 1287def : Pat<(XLenVT (sub 0, (and_oneuse GPR:$rs, 1))), 1288 (SRAI (XLenVT (SLLI $rs, (ImmSubFromXLen (XLenVT 1)))), 1289 (ImmSubFromXLen (XLenVT 1)))>; 1290 1291// AND with leading/trailing ones mask exceeding simm32/simm12. 1292def : Pat<(i64 (and GPR:$rs, LeadingOnesMask:$mask)), 1293 (SLLI (i64 (SRLI $rs, LeadingOnesMask:$mask)), LeadingOnesMask:$mask)>; 1294def : Pat<(XLenVT (and GPR:$rs, TrailingOnesMask:$mask)), 1295 (SRLI (XLenVT (SLLI $rs, TrailingOnesMask:$mask)), TrailingOnesMask:$mask)>; 1296 1297// Match both a plain shift and one where the shift amount is masked (this is 1298// typically introduced when the legalizer promotes the shift amount and 1299// zero-extends it). For RISC-V, the mask is unnecessary as shifts in the base 1300// ISA only read the least significant 5 bits (RV32I) or 6 bits (RV64I). 1301def shiftMaskXLen : ComplexPattern<XLenVT, 1, "selectShiftMaskXLen", [], [], 0>; 1302def shiftMask32 : ComplexPattern<i64, 1, "selectShiftMask32", [], [], 0>; 1303 1304class shiftop<SDPatternOperator operator> 1305 : PatFrag<(ops node:$val, node:$count), 1306 (operator node:$val, (XLenVT (shiftMaskXLen node:$count)))>; 1307class shiftopw<SDPatternOperator operator> 1308 : PatFrag<(ops node:$val, node:$count), 1309 (operator node:$val, (i64 (shiftMask32 node:$count)))>; 1310 1311def : PatGprGpr<shiftop<shl>, SLL>; 1312def : PatGprGpr<shiftop<srl>, SRL>; 1313def : PatGprGpr<shiftop<sra>, SRA>; 1314 1315// This is a special case of the ADD instruction used to facilitate the use of a 1316// fourth operand to emit a relocation on a symbol relating to this instruction. 1317// The relocation does not affect any bits of the instruction itself but is used 1318// as a hint to the linker. 1319let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in 1320def PseudoAddTPRel : Pseudo<(outs GPR:$rd), 1321 (ins GPR:$rs1, GPR:$rs2, tprel_add_symbol:$src), [], 1322 "add", "$rd, $rs1, $rs2, $src">; 1323 1324/// FrameIndex calculations 1325 1326def : Pat<(FrameAddrRegImm (iPTR GPR:$rs1), simm12:$imm12), 1327 (ADDI GPR:$rs1, simm12:$imm12)>; 1328 1329/// HI and ADD_LO address nodes. 1330 1331// Pseudo for a rematerializable LUI+ADDI sequence for loading an address. 1332// It will be expanded after register allocation. 1333// FIXME: The scheduling information does not reflect the multiple instructions. 1334let Size = 8, isReMaterializable = 1 in 1335def PseudoMovAddr : Pseudo<(outs GPR:$dst), (ins uimm20_lui:$hi, simm12:$lo), []>, 1336 Sched<[WriteIALU]>; 1337 1338def riscv_hi_oneuse : unop_oneuse<riscv_hi>; 1339def addr_hi_lo : PatFrag<(ops node:$hi, node:$lo), 1340 (riscv_add_lo (riscv_hi_oneuse node:$hi), node:$lo)>; 1341 1342def : Pat<(addr_hi_lo tglobaladdr:$hi, tglobaladdr:$lo), 1343 (PseudoMovAddr tglobaladdr:$hi, tglobaladdr:$lo)>; 1344def : Pat<(addr_hi_lo tblockaddress:$hi, tblockaddress:$lo), 1345 (PseudoMovAddr tblockaddress:$hi, tblockaddress:$lo)>; 1346def : Pat<(addr_hi_lo tjumptable:$hi, tjumptable:$lo), 1347 (PseudoMovAddr tjumptable:$hi, tjumptable:$lo)>; 1348def : Pat<(addr_hi_lo tconstpool:$hi, tconstpool:$lo), 1349 (PseudoMovAddr tconstpool:$hi, tconstpool:$lo)>; 1350 1351def : Pat<(riscv_hi tglobaladdr:$in), (LUI tglobaladdr:$in)>; 1352def : Pat<(riscv_hi tblockaddress:$in), (LUI tblockaddress:$in)>; 1353def : Pat<(riscv_hi tjumptable:$in), (LUI tjumptable:$in)>; 1354def : Pat<(riscv_hi tconstpool:$in), (LUI tconstpool:$in)>; 1355 1356def : Pat<(riscv_add_lo GPR:$hi, tglobaladdr:$lo), 1357 (ADDI GPR:$hi, tglobaladdr:$lo)>; 1358def : Pat<(riscv_add_lo GPR:$hi, tblockaddress:$lo), 1359 (ADDI GPR:$hi, tblockaddress:$lo)>; 1360def : Pat<(riscv_add_lo GPR:$hi, tjumptable:$lo), 1361 (ADDI GPR:$hi, tjumptable:$lo)>; 1362def : Pat<(riscv_add_lo GPR:$hi, tconstpool:$lo), 1363 (ADDI GPR:$hi, tconstpool:$lo)>; 1364 1365/// TLS address nodes. 1366 1367def : Pat<(riscv_hi tglobaltlsaddr:$in), (LUI tglobaltlsaddr:$in)>; 1368def : Pat<(riscv_add_tprel GPR:$rs1, GPR:$rs2, tglobaltlsaddr:$src), 1369 (PseudoAddTPRel GPR:$rs1, GPR:$rs2, tglobaltlsaddr:$src)>; 1370def : Pat<(riscv_add_lo GPR:$src, tglobaltlsaddr:$lo), 1371 (ADDI GPR:$src, tglobaltlsaddr:$lo)>; 1372 1373/// Setcc 1374 1375def : PatGprGpr<setlt, SLT>; 1376def : PatGprSimm12<setlt, SLTI>; 1377def : PatGprGpr<setult, SLTU>; 1378def : PatGprSimm12<setult, SLTIU>; 1379 1380// RISC-V doesn't have general instructions for integer setne/seteq, but we can 1381// check for equality with 0. These ComplexPatterns rewrite the setne/seteq into 1382// something that can be compared with 0. 1383// These ComplexPatterns must be used in pairs. 1384def riscv_setne : ComplexPattern<XLenVT, 1, "selectSETNE", [setcc]>; 1385def riscv_seteq : ComplexPattern<XLenVT, 1, "selectSETEQ", [setcc]>; 1386 1387// Define pattern expansions for setcc operations that aren't directly 1388// handled by a RISC-V instruction. 1389def : Pat<(riscv_seteq (XLenVT GPR:$rs1)), (SLTIU GPR:$rs1, 1)>; 1390def : Pat<(riscv_setne (XLenVT GPR:$rs1)), (SLTU (XLenVT X0), GPR:$rs1)>; 1391def : Pat<(XLenVT (setne (XLenVT GPR:$rs1), -1)), (SLTIU GPR:$rs1, -1)>; 1392 1393def IntCCtoRISCVCC : SDNodeXForm<riscv_selectcc, [{ 1394 ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get(); 1395 RISCVCC::CondCode BrCC = getRISCVCCForIntCC(CC); 1396 return CurDAG->getTargetConstant(BrCC, SDLoc(N), Subtarget->getXLenVT()); 1397}]>; 1398 1399def riscv_selectcc_frag : PatFrag<(ops node:$lhs, node:$rhs, node:$cc, 1400 node:$truev, node:$falsev), 1401 (riscv_selectcc node:$lhs, node:$rhs, 1402 node:$cc, node:$truev, 1403 node:$falsev), [{}], 1404 IntCCtoRISCVCC>; 1405 1406multiclass SelectCC_GPR_rrirr<DAGOperand valty, ValueType vt> { 1407 let usesCustomInserter = 1 in 1408 def _Using_CC_GPR : Pseudo<(outs valty:$dst), 1409 (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc, 1410 valty:$truev, valty:$falsev), 1411 [(set valty:$dst, 1412 (riscv_selectcc_frag:$cc (XLenVT GPR:$lhs), GPR:$rhs, cond, 1413 (vt valty:$truev), valty:$falsev))]>; 1414 // Explicitly select 0 in the condition to X0. The register coalescer doesn't 1415 // always do it. 1416 def : Pat<(riscv_selectcc_frag:$cc (XLenVT GPR:$lhs), 0, cond, (vt valty:$truev), 1417 valty:$falsev), 1418 (!cast<Instruction>(NAME#"_Using_CC_GPR") GPR:$lhs, (XLenVT X0), 1419 (IntCCtoRISCVCC $cc), valty:$truev, valty:$falsev)>; 1420} 1421 1422let Predicates = [NoConditionalMoveFusion] in 1423defm Select_GPR : SelectCC_GPR_rrirr<GPR, XLenVT>; 1424 1425class SelectCompressOpt<CondCode Cond> 1426 : Pat<(riscv_selectcc_frag:$select (XLenVT GPR:$lhs), simm12_no6:$Constant, Cond, 1427 (XLenVT GPR:$truev), GPR:$falsev), 1428 (Select_GPR_Using_CC_GPR (XLenVT (ADDI GPR:$lhs, (NegImm simm12:$Constant))), (XLenVT X0), 1429 (IntCCtoRISCVCC $select), GPR:$truev, GPR:$falsev)>; 1430 1431def OptForMinSize : Predicate<"MF ? MF->getFunction().hasMinSize() : false">; 1432 1433let Predicates = [HasStdExtC, OptForMinSize] in { 1434 def : SelectCompressOpt<SETEQ>; 1435 def : SelectCompressOpt<SETNE>; 1436} 1437 1438/// Branches and jumps 1439 1440// Match `riscv_brcc` and lower to the appropriate RISC-V branch instruction. 1441multiclass BccPat<CondCode Cond, RVInstB Inst> { 1442 def : Pat<(riscv_brcc (XLenVT GPR:$rs1), GPR:$rs2, Cond, bb:$imm12), 1443 (Inst GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12)>; 1444 // Explicitly select 0 to X0. The register coalescer doesn't always do it. 1445 def : Pat<(riscv_brcc (XLenVT GPR:$rs1), 0, Cond, bb:$imm12), 1446 (Inst GPR:$rs1, (XLenVT X0), simm13_lsb0:$imm12)>; 1447} 1448 1449class BrccCompressOpt<CondCode Cond, RVInstB Inst> 1450 : Pat<(riscv_brcc GPR:$lhs, simm12_no6:$Constant, Cond, bb:$place), 1451 (Inst (XLenVT (ADDI GPR:$lhs, (NegImm simm12:$Constant))), 1452 (XLenVT X0), bb:$place)>; 1453 1454defm : BccPat<SETEQ, BEQ>; 1455defm : BccPat<SETNE, BNE>; 1456defm : BccPat<SETLT, BLT>; 1457defm : BccPat<SETGE, BGE>; 1458defm : BccPat<SETULT, BLTU>; 1459defm : BccPat<SETUGE, BGEU>; 1460 1461let Predicates = [HasStdExtCOrZca, OptForMinSize] in { 1462 def : BrccCompressOpt<SETEQ, BEQ>; 1463 def : BrccCompressOpt<SETNE, BNE>; 1464} 1465 1466class LongBccPseudo : Pseudo<(outs), 1467 (ins GPR:$rs1, GPR:$rs2, simm21_lsb0_jal:$imm20), 1468 []> { 1469 let Size = 8; 1470 let isBarrier = 1; 1471 let isBranch = 1; 1472 let hasSideEffects = 0; 1473 let mayStore = 0; 1474 let mayLoad = 0; 1475 let isAsmParserOnly = 1; 1476 let hasNoSchedulingInfo = 1; 1477} 1478 1479def PseudoLongBEQ : LongBccPseudo; 1480def PseudoLongBNE : LongBccPseudo; 1481def PseudoLongBLT : LongBccPseudo; 1482def PseudoLongBGE : LongBccPseudo; 1483def PseudoLongBLTU : LongBccPseudo; 1484def PseudoLongBGEU : LongBccPseudo; 1485 1486let isBarrier = 1, isBranch = 1, isTerminator = 1 in 1487def PseudoBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>, 1488 PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>; 1489 1490let Predicates = [NoStdExtZicfilp], 1491 isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in 1492def PseudoBRIND : Pseudo<(outs), (ins GPRJALR:$rs1, simm12:$imm12), []>, 1493 PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; 1494 1495let Predicates = [HasStdExtZicfilp], 1496 isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in { 1497def PseudoBRINDNonX7 : Pseudo<(outs), (ins GPRJALRNonX7:$rs1, simm12:$imm12), []>, 1498 PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; 1499def PseudoBRINDX7 : Pseudo<(outs), (ins GPRX7:$rs1, simm12:$imm12), []>, 1500 PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; 1501} 1502 1503// For Zicfilp, need to avoid using X7/T2 for indirect branches which need 1504// landing pad. 1505let Predicates = [HasStdExtZicfilp] in { 1506def : Pat<(brind GPRJALRNonX7:$rs1), (PseudoBRINDNonX7 GPRJALRNonX7:$rs1, 0)>; 1507def : Pat<(brind (add GPRJALRNonX7:$rs1, simm12:$imm12)), 1508 (PseudoBRINDNonX7 GPRJALRNonX7:$rs1, simm12:$imm12)>; 1509 1510def : Pat<(riscv_sw_guarded_brind GPRX7:$rs1), (PseudoBRINDX7 GPRX7:$rs1, 0)>; 1511def : Pat<(riscv_sw_guarded_brind (add GPRX7:$rs1, simm12:$imm12)), 1512 (PseudoBRINDX7 GPRX7:$rs1, simm12:$imm12)>; 1513} 1514 1515let Predicates = [NoStdExtZicfilp] in { 1516def : Pat<(brind GPRJALR:$rs1), (PseudoBRIND GPRJALR:$rs1, 0)>; 1517def : Pat<(brind (add GPRJALR:$rs1, simm12:$imm12)), 1518 (PseudoBRIND GPRJALR:$rs1, simm12:$imm12)>; 1519} 1520 1521// PseudoCALLReg is a generic pseudo instruction for calls which will eventually 1522// expand to auipc and jalr while encoding, with any given register used as the 1523// destination. 1524// Define AsmString to print "call" when compile with -S flag. 1525// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction. 1526let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, Size = 8, hasSideEffects = 0, 1527 mayStore = 0, mayLoad = 0 in 1528def PseudoCALLReg : Pseudo<(outs GPR:$rd), (ins call_symbol:$func), [], 1529 "call", "$rd, $func">, 1530 Sched<[WriteIALU, WriteJalr, ReadJalr]>; 1531 1532// PseudoCALL is a pseudo instruction which will eventually expand to auipc 1533// and jalr while encoding. This is desirable, as an auipc+jalr pair with 1534// R_RISCV_CALL and R_RISCV_RELAX relocations can be be relaxed by the linker 1535// if the offset fits in a signed 21-bit immediate. 1536// Define AsmString to print "call" when compile with -S flag. 1537// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction. 1538let isCall = 1, Defs = [X1], isCodeGenOnly = 0, Size = 8 in 1539def PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), [], 1540 "call", "$func">, 1541 Sched<[WriteIALU, WriteJalr, ReadJalr]>; 1542 1543def : Pat<(riscv_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>; 1544def : Pat<(riscv_call texternalsym:$func), (PseudoCALL texternalsym:$func)>; 1545 1546def : Pat<(riscv_sret_glue), (SRET (XLenVT X0), (XLenVT X0))>; 1547def : Pat<(riscv_mret_glue), (MRET (XLenVT X0), (XLenVT X0))>; 1548 1549let isCall = 1, Defs = [X1] in { 1550let Predicates = [NoStdExtZicfilp] in 1551def PseudoCALLIndirect : Pseudo<(outs), (ins GPRJALR:$rs1), 1552 [(riscv_call GPRJALR:$rs1)]>, 1553 PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>; 1554let Predicates = [HasStdExtZicfilp] in 1555def PseudoCALLIndirectNonX7 : Pseudo<(outs), (ins GPRJALRNonX7:$rs1), 1556 [(riscv_call GPRJALRNonX7:$rs1)]>, 1557 PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>; 1558} 1559 1560let isBarrier = 1, isReturn = 1, isTerminator = 1 in 1561def PseudoRET : Pseudo<(outs), (ins), [(riscv_ret_glue)]>, 1562 PseudoInstExpansion<(JALR X0, X1, 0)>; 1563 1564// PseudoTAIL is a pseudo instruction similar to PseudoCALL and will eventually 1565// expand to auipc and jalr while encoding. 1566// Define AsmString to print "tail" when compile with -S flag. 1567let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2], 1568 Size = 8, isCodeGenOnly = 0 in 1569def PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), [], 1570 "tail", "$dst">, 1571 Sched<[WriteIALU, WriteJalr, ReadJalr]>; 1572 1573let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in { 1574let Predicates = [NoStdExtZicfilp] in 1575def PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1), 1576 [(riscv_tail GPRTC:$rs1)]>, 1577 PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>; 1578let Predicates = [HasStdExtZicfilp] in 1579def PseudoTAILIndirectNonX7 : Pseudo<(outs), (ins GPRTCNonX7:$rs1), 1580 [(riscv_tail GPRTCNonX7:$rs1)]>, 1581 PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>; 1582} 1583 1584def : Pat<(riscv_tail (iPTR tglobaladdr:$dst)), 1585 (PseudoTAIL tglobaladdr:$dst)>; 1586def : Pat<(riscv_tail (iPTR texternalsym:$dst)), 1587 (PseudoTAIL texternalsym:$dst)>; 1588 1589let isCall = 0, isBarrier = 1, isBranch = 1, isTerminator = 1, Size = 8, 1590 isCodeGenOnly = 0, hasSideEffects = 0, mayStore = 0, mayLoad = 0 in 1591def PseudoJump : Pseudo<(outs GPR:$rd), (ins pseudo_jump_symbol:$target), [], 1592 "jump", "$target, $rd">, 1593 Sched<[WriteIALU, WriteJalr, ReadJalr]>; 1594 1595// Pseudo for a rematerializable constant materialization sequence. 1596// This is an experimental feature enabled by 1597// -riscv-use-rematerializable-movimm in RISCVISelDAGToDAG.cpp 1598// It will be expanded after register allocation. 1599// FIXME: The scheduling information does not reflect the multiple instructions. 1600let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, 1601 isReMaterializable = 1 in 1602def PseudoMovImm : Pseudo<(outs GPR:$dst), (ins i32imm:$imm), []>, 1603 Sched<[WriteIALU]>; 1604 1605let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0, 1606 isAsmParserOnly = 1 in 1607def PseudoLLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1608 "lla", "$dst, $src">; 1609 1610// Refer to comment on PseudoLI for explanation of Size=32 1611let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0, 1612 isAsmParserOnly = 1 in 1613def PseudoLLAImm : Pseudo<(outs GPR:$dst), (ins ixlenimm_li_restricted:$imm), [], 1614 "lla", "$dst, $imm">; 1615def : Pat<(riscv_lla tglobaladdr:$in), (PseudoLLA tglobaladdr:$in)>; 1616def : Pat<(riscv_lla tblockaddress:$in), (PseudoLLA tblockaddress:$in)>; 1617def : Pat<(riscv_lla tjumptable:$in), (PseudoLLA tjumptable:$in)>; 1618def : Pat<(riscv_lla tconstpool:$in), (PseudoLLA tconstpool:$in)>; 1619 1620let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0, 1621 isAsmParserOnly = 1 in 1622def PseudoLGA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1623 "lga", "$dst, $src">; 1624 1625let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0, 1626 isAsmParserOnly = 1 in 1627def PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1628 "la", "$dst, $src">; 1629 1630// Refer to comment on PseudoLI for explanation of Size=32 1631let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32, 1632 isCodeGenOnly = 0, isAsmParserOnly = 1 in 1633def PseudoLAImm : Pseudo<(outs GPR:$rd), (ins ixlenimm_li_restricted:$imm), [], 1634 "la", "$rd, $imm">; 1635 1636let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0, 1637 isAsmParserOnly = 1 in 1638def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1639 "la.tls.ie", "$dst, $src">; 1640 1641let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0, 1642 isAsmParserOnly = 1 in 1643def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1644 "la.tls.gd", "$dst, $src">; 1645 1646let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 32, isCodeGenOnly = 0 in 1647def PseudoLA_TLSDESC : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1648 "la.tlsdesc", "$dst, $src">; 1649 1650def TLSDESCCallSymbol : AsmOperandClass { 1651 let Name = "TLSDESCCallSymbol"; 1652 let RenderMethod = "addImmOperands"; 1653 let DiagnosticType = "InvalidTLSDESCCallSymbol"; 1654 let ParserMethod = "parseOperandWithModifier"; 1655} 1656 1657// A bare symbol with the %tlsdesc_call variant. 1658def tlsdesc_call_symbol : Operand<XLenVT> { 1659 let ParserMatchClass = TLSDESCCallSymbol; 1660} 1661// This is a special case of the JALR instruction used to facilitate the use of a 1662// fourth operand to emit a relocation on a symbol relating to this instruction. 1663// The relocation does not affect any bits of the instruction itself but is used 1664// as a hint to the linker. 1665let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, Size = 8, hasSideEffects = 0, 1666 mayStore = 0, mayLoad = 0 in 1667def PseudoTLSDESCCall : Pseudo<(outs GPR:$rd), 1668 (ins GPR:$rs1, simm12:$imm12, tlsdesc_call_symbol:$src), [], 1669 "jalr", "$rd, ${imm12}(${rs1}), $src">, 1670 Sched<[WriteJalr, ReadJalr]> { 1671 let Defs = [X10]; 1672 let Uses = [X10]; 1673} 1674 1675 1676/// Sign/Zero Extends 1677 1678// There are single-instruction versions of these in Zbb, so disable these 1679// Pseudos if that extension is present. 1680let hasSideEffects = 0, mayLoad = 0, 1681 mayStore = 0, isCodeGenOnly = 0, isAsmParserOnly = 1 in { 1682def PseudoSEXT_B : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.b", "$rd, $rs">; 1683def PseudoSEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.h", "$rd, $rs">; 1684// rv64's sext.w is defined above, using InstAlias<"sext.w ... 1685// zext.b is defined above, using InstAlias<"zext.b ... 1686def PseudoZEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.h", "$rd, $rs">; 1687} // hasSideEffects = 0, ... 1688 1689let Predicates = [IsRV64], hasSideEffects = 0, mayLoad = 0, mayStore = 0, 1690 isCodeGenOnly = 0, isAsmParserOnly = 1 in { 1691def PseudoZEXT_W : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.w", "$rd, $rs">; 1692} // Predicates = [IsRV64], ... 1693 1694/// Loads 1695 1696class LdPat<PatFrag LoadOp, RVInst Inst, ValueType vt = XLenVT> 1697 : Pat<(vt (LoadOp (AddrRegImm (XLenVT GPR:$rs1), simm12:$imm12))), 1698 (Inst GPR:$rs1, simm12:$imm12)>; 1699 1700def : LdPat<sextloadi8, LB>; 1701def : LdPat<extloadi8, LBU>; // Prefer unsigned due to no c.lb in Zcb. 1702def : LdPat<sextloadi16, LH>; 1703def : LdPat<extloadi16, LH>; 1704def : LdPat<load, LW, i32>; 1705def : LdPat<zextloadi8, LBU>; 1706def : LdPat<zextloadi16, LHU>; 1707 1708/// Stores 1709 1710class StPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy, 1711 ValueType vt> 1712 : Pat<(StoreOp (vt StTy:$rs2), (AddrRegImm (XLenVT GPR:$rs1), 1713 simm12:$imm12)), 1714 (Inst StTy:$rs2, GPR:$rs1, simm12:$imm12)>; 1715 1716def : StPat<truncstorei8, SB, GPR, XLenVT>; 1717def : StPat<truncstorei16, SH, GPR, XLenVT>; 1718def : StPat<store, SW, GPR, i32>; 1719 1720/// Fences 1721 1722// Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set 1723// Manual: Volume I. 1724 1725// fence acquire -> fence r, rw 1726def : Pat<(atomic_fence (XLenVT 4), (timm)), (FENCE 0b10, 0b11)>; 1727// fence release -> fence rw, w 1728def : Pat<(atomic_fence (XLenVT 5), (timm)), (FENCE 0b11, 0b1)>; 1729// fence acq_rel -> fence.tso 1730def : Pat<(atomic_fence (XLenVT 6), (timm)), (FENCE_TSO)>; 1731// fence seq_cst -> fence rw, rw 1732def : Pat<(atomic_fence (XLenVT 7), (timm)), (FENCE 0b11, 0b11)>; 1733 1734// Lowering for atomic load and store is defined in RISCVInstrInfoA.td. 1735// Although these are lowered to fence+load/store instructions defined in the 1736// base RV32I/RV64I ISA, this lowering is only used when the A extension is 1737// present. This is necessary as it isn't valid to mix __atomic_* libcalls 1738// with inline atomic operations for the same object. 1739 1740/// Access to system registers 1741 1742// Helpers for defining specific operations. They are defined for each system 1743// register separately. Side effect is not used because dependencies are 1744// expressed via use-def properties. 1745 1746class ReadSysReg<SysReg SR, list<Register> Regs> 1747 : Pseudo<(outs GPR:$rd), (ins), 1748 [(set GPR:$rd, (XLenVT (riscv_read_csr (XLenVT SR.Encoding))))]>, 1749 PseudoInstExpansion<(CSRRS GPR:$rd, SR.Encoding, X0)> { 1750 let hasSideEffects = 0; 1751 let Uses = Regs; 1752} 1753 1754class WriteSysReg<SysReg SR, list<Register> Regs> 1755 : Pseudo<(outs), (ins GPR:$val), 1756 [(riscv_write_csr (XLenVT SR.Encoding), (XLenVT GPR:$val))]>, 1757 PseudoInstExpansion<(CSRRW X0, SR.Encoding, GPR:$val)> { 1758 let hasSideEffects = 0; 1759 let Defs = Regs; 1760} 1761 1762class WriteSysRegImm<SysReg SR, list<Register> Regs> 1763 : Pseudo<(outs), (ins uimm5:$val), 1764 [(riscv_write_csr (XLenVT SR.Encoding), uimm5:$val)]>, 1765 PseudoInstExpansion<(CSRRWI X0, SR.Encoding, uimm5:$val)> { 1766 let hasSideEffects = 0; 1767 let Defs = Regs; 1768} 1769 1770class SwapSysReg<SysReg SR, list<Register> Regs> 1771 : Pseudo<(outs GPR:$rd), (ins GPR:$val), 1772 [(set GPR:$rd, (riscv_swap_csr (XLenVT SR.Encoding), (XLenVT GPR:$val)))]>, 1773 PseudoInstExpansion<(CSRRW GPR:$rd, SR.Encoding, GPR:$val)> { 1774 let hasSideEffects = 0; 1775 let Uses = Regs; 1776 let Defs = Regs; 1777} 1778 1779class SwapSysRegImm<SysReg SR, list<Register> Regs> 1780 : Pseudo<(outs GPR:$rd), (ins uimm5:$val), 1781 [(set GPR:$rd, (XLenVT (riscv_swap_csr (XLenVT SR.Encoding), uimm5:$val)))]>, 1782 PseudoInstExpansion<(CSRRWI GPR:$rd, SR.Encoding, uimm5:$val)> { 1783 let hasSideEffects = 0; 1784 let Uses = Regs; 1785 let Defs = Regs; 1786} 1787 1788def ReadFRM : ReadSysReg<SysRegFRM, [FRM]>; 1789def WriteFRM : WriteSysReg<SysRegFRM, [FRM]>; 1790def WriteFRMImm : WriteSysRegImm<SysRegFRM, [FRM]>; 1791def SwapFRMImm : SwapSysRegImm<SysRegFRM, [FRM]>; 1792 1793def WriteVXRMImm : WriteSysRegImm<SysRegVXRM, [VXRM]>; 1794 1795let hasSideEffects = true in { 1796def ReadFFLAGS : ReadSysReg<SysRegFFLAGS, [FFLAGS]>; 1797def WriteFFLAGS : WriteSysReg<SysRegFFLAGS, [FFLAGS]>; 1798} 1799/// Other pseudo-instructions 1800 1801// Pessimistically assume the stack pointer will be clobbered 1802let Defs = [X2], Uses = [X2] in { 1803def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 1804 [(callseq_start timm:$amt1, timm:$amt2)]>; 1805def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 1806 [(callseq_end timm:$amt1, timm:$amt2)]>; 1807} // Defs = [X2], Uses = [X2] 1808 1809/// RV64 patterns 1810 1811let Predicates = [IsRV64, NotHasStdExtZba] in { 1812def : Pat<(i64 (and GPR:$rs1, 0xffffffff)), (SRLI (i64 (SLLI GPR:$rs1, 32)), 32)>; 1813 1814// If we're shifting a 32-bit zero extended value left by 0-31 bits, use 2 1815// shifts instead of 3. This can occur when unsigned is used to index an array. 1816def : Pat<(i64 (shl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)), 1817 (SRLI (i64 (SLLI GPR:$rs1, 32)), (ImmSubFrom32 uimm5:$shamt))>; 1818} 1819 1820class binop_allhusers<SDPatternOperator operator> 1821 : PatFrag<(ops node:$lhs, node:$rhs), 1822 (XLenVT (operator node:$lhs, node:$rhs)), [{ 1823 return hasAllHUsers(Node); 1824}]>; 1825 1826// PatFrag to allow ADDW/SUBW/MULW/SLLW to be selected from i64 add/sub/mul/shl 1827// if only the lower 32 bits of their result is used. 1828class binop_allwusers<SDPatternOperator operator> 1829 : PatFrag<(ops node:$lhs, node:$rhs), 1830 (i64 (operator node:$lhs, node:$rhs)), [{ 1831 return hasAllWUsers(Node); 1832}]>; 1833 1834def sexti32_allwusers : PatFrag<(ops node:$src), 1835 (sext_inreg node:$src, i32), [{ 1836 return hasAllWUsers(Node); 1837}]>; 1838 1839def ImmSExt32 : SDNodeXForm<imm, [{ 1840 return CurDAG->getTargetConstant(SignExtend64<32>(N->getSExtValue()), 1841 SDLoc(N), N->getValueType(0)); 1842}]>; 1843// Look for constants where the upper 32 bits are 0, but sign extending bit 31 1844// would be an simm12. 1845def u32simm12 : ImmLeaf<XLenVT, [{ 1846 return isUInt<32>(Imm) && isInt<12>(SignExtend64<32>(Imm)); 1847}], ImmSExt32>; 1848 1849let Predicates = [IsRV64] in { 1850 1851def : Pat<(i64 (and GPR:$rs, LeadingOnesWMask:$mask)), 1852 (SLLI (i64 (SRLIW $rs, LeadingOnesWMask:$mask)), LeadingOnesWMask:$mask)>; 1853 1854/// sext and zext 1855 1856// Sign extend is not needed if all users are W instructions. 1857def : Pat<(sexti32_allwusers GPR:$rs1), (XLenVT GPR:$rs1)>; 1858 1859def : Pat<(sext_inreg GPR:$rs1, i32), (ADDIW GPR:$rs1, 0)>; 1860 1861/// ALU operations 1862 1863def : Pat<(i64 (srl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)), 1864 (SRLIW GPR:$rs1, uimm5:$shamt)>; 1865def : Pat<(i64 (srl (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt)), 1866 (SRLIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>; 1867def : Pat<(sra (sext_inreg GPR:$rs1, i32), uimm5:$shamt), 1868 (SRAIW GPR:$rs1, uimm5:$shamt)>; 1869def : Pat<(i64 (sra (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt)), 1870 (SRAIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>; 1871 1872def : PatGprGpr<shiftopw<riscv_sllw>, SLLW>; 1873def : PatGprGpr<shiftopw<riscv_srlw>, SRLW>; 1874def : PatGprGpr<shiftopw<riscv_sraw>, SRAW>; 1875 1876// Select W instructions if only the lower 32 bits of the result are used. 1877def : PatGprGpr<binop_allwusers<add>, ADDW>; 1878def : PatGprSimm12<binop_allwusers<add>, ADDIW>; 1879def : PatGprGpr<binop_allwusers<sub>, SUBW>; 1880def : PatGprImm<binop_allwusers<shl>, SLLIW, uimm5>; 1881 1882// If this is a shr of a value sign extended from i32, and all the users only 1883// use the lower 32 bits, we can use an sraiw to remove the sext_inreg. This 1884// occurs because SimplifyDemandedBits prefers srl over sra. 1885def : Pat<(binop_allwusers<srl> (sext_inreg GPR:$rs1, i32), uimm5:$shamt), 1886 (SRAIW GPR:$rs1, uimm5:$shamt)>; 1887 1888// Use binop_allwusers to recover immediates that may have been broken by 1889// SimplifyDemandedBits. 1890def : Pat<(binop_allwusers<and> GPR:$rs1, 0xffffffff), 1891 (COPY GPR:$rs1)>; 1892def : Pat<(binop_allwusers<and> GPR:$rs1, u32simm12:$imm), 1893 (ANDI GPR:$rs1, u32simm12:$imm)>; 1894 1895def : Pat<(binop_allwusers<or> GPR:$rs1, u32simm12:$imm), 1896 (ORI GPR:$rs1, u32simm12:$imm)>; 1897 1898def : Pat<(binop_allwusers<xor> GPR:$rs1, u32simm12:$imm), 1899 (XORI GPR:$rs1, u32simm12:$imm)>; 1900/// Loads 1901 1902def : LdPat<sextloadi32, LW, i64>; 1903def : LdPat<extloadi32, LW, i64>; 1904def : LdPat<zextloadi32, LWU, i64>; 1905def : LdPat<load, LD, i64>; 1906 1907/// Stores 1908 1909def : StPat<truncstorei32, SW, GPR, i64>; 1910def : StPat<store, SD, GPR, i64>; 1911} // Predicates = [IsRV64] 1912 1913// On RV64, we can directly read these 64-bit counter CSRs. 1914let Predicates = [IsRV64] in { 1915/// readcyclecounter 1916def : Pat<(i64 (readcyclecounter)), (CSRRS CYCLE.Encoding, (XLenVT X0))>; 1917/// readsteadycounter 1918def : Pat<(i64 (readsteadycounter)), (CSRRS TIME.Encoding, (XLenVT X0))>; 1919} 1920 1921// On RV32, ReadCounterWide will be expanded to the suggested loop reading both 1922// halves of 64-bit counter CSRs. 1923let Predicates = [IsRV32], usesCustomInserter = 1, hasNoSchedulingInfo = 1 in 1924def ReadCounterWide : Pseudo<(outs GPR:$lo, GPR:$hi), (ins i32imm:$csr_lo, i32imm:$csr_hi), 1925 [(set GPR:$lo, GPR:$hi, 1926 (riscv_read_counter_wide csr_sysreg:$csr_lo, csr_sysreg:$csr_hi))], 1927 "", "">; 1928 1929/// traps 1930 1931// We lower `trap` to `unimp`, as this causes a hard exception on nearly all 1932// systems. 1933def : Pat<(trap), (UNIMP)>; 1934 1935// We lower `debugtrap` to `ebreak`, as this will get the attention of the 1936// debugger if possible. 1937def : Pat<(debugtrap), (EBREAK)>; 1938 1939let Predicates = [IsRV64], Uses = [X5], 1940 Defs = [X1, X6, X7, X28, X29, X30, X31], Size = 8 in 1941def HWASAN_CHECK_MEMACCESS_SHORTGRANULES 1942 : Pseudo<(outs), (ins GPRJALR:$ptr, i32imm:$accessinfo), 1943 [(int_hwasan_check_memaccess_shortgranules (i64 X5), GPRJALR:$ptr, 1944 (i32 timm:$accessinfo))]>; 1945 1946// This gets lowered into a 20-byte instruction sequence (at most) 1947let hasSideEffects = 0, mayLoad = 1, mayStore = 0, 1948 Defs = [ X6, X7, X28, X29, X30, X31 ], Size = 20 in { 1949def KCFI_CHECK 1950 : Pseudo<(outs), (ins GPRJALR:$ptr, i32imm:$type), []>, Sched<[]>; 1951} 1952 1953/// Simple optimization 1954def : Pat<(XLenVT (add GPR:$rs1, (AddiPair:$rs2))), 1955 (ADDI (XLenVT (ADDI GPR:$rs1, (AddiPairImmLarge AddiPair:$rs2))), 1956 (AddiPairImmSmall GPR:$rs2))>; 1957 1958let Predicates = [IsRV64] in { 1959// Select W instructions if only the lower 32-bits of the result are used. 1960def : Pat<(binop_allwusers<add> GPR:$rs1, (AddiPair:$rs2)), 1961 (ADDIW (i64 (ADDIW GPR:$rs1, (AddiPairImmLarge AddiPair:$rs2))), 1962 (AddiPairImmSmall AddiPair:$rs2))>; 1963} 1964 1965//===----------------------------------------------------------------------===// 1966// Experimental RV64 i32 legalization patterns. 1967//===----------------------------------------------------------------------===// 1968 1969def simm12i32 : ImmLeaf<i32, [{return isInt<12>(Imm);}]>; 1970 1971// Convert from i32 immediate to i64 target immediate to make SelectionDAG type 1972// checking happy so we can use ADDIW which expects an XLen immediate. 1973def as_i64imm : SDNodeXForm<imm, [{ 1974 return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i64); 1975}]>; 1976 1977def zext_is_sext : PatFrag<(ops node:$src), (zext node:$src), [{ 1978 KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0), 0); 1979 return Known.isNonNegative(); 1980}]>; 1981 1982let Predicates = [IsRV64] in { 1983def : LdPat<sextloadi8, LB, i32>; 1984def : LdPat<extloadi8, LBU, i32>; // Prefer unsigned due to no c.lb in Zcb. 1985def : LdPat<sextloadi16, LH, i32>; 1986def : LdPat<extloadi16, LH, i32>; 1987def : LdPat<zextloadi8, LBU, i32>; 1988def : LdPat<zextloadi16, LHU, i32>; 1989 1990def : StPat<truncstorei8, SB, GPR, i32>; 1991def : StPat<truncstorei16, SH, GPR, i32>; 1992 1993def : Pat<(anyext GPR:$src), (COPY GPR:$src)>; 1994def : Pat<(sext GPR:$src), (ADDIW GPR:$src, 0)>; 1995def : Pat<(trunc GPR:$src), (COPY GPR:$src)>; 1996 1997def : PatGprGpr<add, ADDW, i32, i32>; 1998def : PatGprGpr<sub, SUBW, i32, i32>; 1999def : PatGprGpr<and, AND, i32, i32>; 2000def : PatGprGpr<or, OR, i32, i32>; 2001def : PatGprGpr<xor, XOR, i32, i32>; 2002def : PatGprGpr<shiftopw<shl>, SLLW, i32, i64>; 2003def : PatGprGpr<shiftopw<srl>, SRLW, i32, i64>; 2004def : PatGprGpr<shiftopw<sra>, SRAW, i32, i64>; 2005 2006def : Pat<(i32 (add GPR:$rs1, simm12i32:$imm)), 2007 (ADDIW GPR:$rs1, (i64 (as_i64imm $imm)))>; 2008def : Pat<(i32 (and GPR:$rs1, simm12i32:$imm)), 2009 (ANDI GPR:$rs1, (i64 (as_i64imm $imm)))>; 2010def : Pat<(i32 (or GPR:$rs1, simm12i32:$imm)), 2011 (ORI GPR:$rs1, (i64 (as_i64imm $imm)))>; 2012def : Pat<(i32 (xor GPR:$rs1, simm12i32:$imm)), 2013 (XORI GPR:$rs1, (i64 (as_i64imm $imm)))>; 2014 2015def : PatGprImm<shl, SLLIW, uimm5, i32>; 2016def : PatGprImm<srl, SRLIW, uimm5, i32>; 2017def : PatGprImm<sra, SRAIW, uimm5, i32>; 2018 2019def : Pat<(i32 (and GPR:$rs, TrailingOnesMask:$mask)), 2020 (SRLI (i32 (SLLI $rs, (i64 (XLenSubTrailingOnes $mask)))), 2021 (i64 (XLenSubTrailingOnes $mask)))>; 2022 2023// Use sext if the sign bit of the input is 0. 2024def : Pat<(zext_is_sext GPR:$src), (ADDIW GPR:$src, 0)>; 2025} 2026 2027let Predicates = [IsRV64, NotHasStdExtZba] in { 2028def : Pat<(zext GPR:$src), (SRLI (i64 (SLLI GPR:$src, 32)), 32)>; 2029 2030// If we're shifting a 32-bit zero extended value left by 0-31 bits, use 2 2031// shifts instead of 3. This can occur when unsigned is used to index an array. 2032def : Pat<(shl (zext GPR:$rs), uimm5:$shamt), 2033 (SRLI (i64 (SLLI GPR:$rs, 32)), (ImmSubFrom32 uimm5:$shamt))>; 2034} 2035 2036//===----------------------------------------------------------------------===// 2037// Standard extensions 2038//===----------------------------------------------------------------------===// 2039 2040// Multiply and Division 2041include "RISCVInstrInfoM.td" 2042 2043// Atomic 2044include "RISCVInstrInfoA.td" 2045include "RISCVInstrInfoZa.td" 2046include "RISCVInstrInfoZalasr.td" 2047 2048// Scalar FP 2049include "RISCVInstrInfoF.td" 2050include "RISCVInstrInfoD.td" 2051include "RISCVInstrInfoZfh.td" 2052include "RISCVInstrInfoZfbfmin.td" 2053include "RISCVInstrInfoZfa.td" 2054 2055// Scalar bitmanip and cryptography 2056include "RISCVInstrInfoZb.td" 2057include "RISCVInstrInfoZk.td" 2058 2059// Vector 2060include "RISCVInstrInfoV.td" 2061include "RISCVInstrInfoZvk.td" 2062 2063// Compressed 2064include "RISCVInstrInfoC.td" 2065include "RISCVInstrInfoZc.td" 2066include "RISCVInstrInfoZcmop.td" 2067 2068// Integer 2069include "RISCVInstrInfoZimop.td" 2070include "RISCVInstrInfoZicbo.td" 2071include "RISCVInstrInfoZicond.td" 2072include "RISCVInstrInfoZicfiss.td" 2073 2074//===----------------------------------------------------------------------===// 2075// Vendor extensions 2076//===----------------------------------------------------------------------===// 2077 2078include "RISCVInstrInfoXVentana.td" 2079include "RISCVInstrInfoXTHead.td" 2080include "RISCVInstrInfoXSf.td" 2081include "RISCVInstrInfoSFB.td" 2082include "RISCVInstrInfoXCV.td" 2083include "RISCVInstrInfoXwch.td" 2084 2085//===----------------------------------------------------------------------===// 2086// Global ISel 2087//===----------------------------------------------------------------------===// 2088 2089include "RISCVInstrGISel.td" 2090