1//===-- RISCVInstrInfo.td - Target Description for RISCV ---*- 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_RISCVReadCycleWide : SDTypeProfile<2, 0, [SDTCisVT<0, i32>, 37 SDTCisVT<1, i32>]>; 38def SDT_RISCVIntUnaryOpW : SDTypeProfile<1, 1, [ 39 SDTCisSameAs<0, 1>, SDTCisVT<0, i64> 40]>; 41def SDT_RISCVIntBinOpW : SDTypeProfile<1, 2, [ 42 SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64> 43]>; 44def SDT_RISCVIntShiftDOpW : SDTypeProfile<1, 3, [ 45 SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64>, SDTCisVT<3, i64> 46]>; 47 48// Target-independent nodes, but with target-specific formats. 49def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart, 50 [SDNPHasChain, SDNPOutGlue]>; 51def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd, 52 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; 53 54// Target-dependent nodes. 55def riscv_call : SDNode<"RISCVISD::CALL", SDT_RISCVCall, 56 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, 57 SDNPVariadic]>; 58def riscv_ret_flag : SDNode<"RISCVISD::RET_FLAG", SDTNone, 59 [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; 60def riscv_uret_flag : SDNode<"RISCVISD::URET_FLAG", SDTNone, 61 [SDNPHasChain, SDNPOptInGlue]>; 62def riscv_sret_flag : SDNode<"RISCVISD::SRET_FLAG", SDTNone, 63 [SDNPHasChain, SDNPOptInGlue]>; 64def riscv_mret_flag : SDNode<"RISCVISD::MRET_FLAG", 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_sllw : SDNode<"RISCVISD::SLLW", SDT_RISCVIntBinOpW>; 73def riscv_sraw : SDNode<"RISCVISD::SRAW", SDT_RISCVIntBinOpW>; 74def riscv_srlw : SDNode<"RISCVISD::SRLW", SDT_RISCVIntBinOpW>; 75def riscv_read_csr : SDNode<"RISCVISD::READ_CSR", SDT_RISCVReadCSR, 76 [SDNPHasChain]>; 77def riscv_write_csr : SDNode<"RISCVISD::WRITE_CSR", SDT_RISCVWriteCSR, 78 [SDNPHasChain]>; 79def riscv_swap_csr : SDNode<"RISCVISD::SWAP_CSR", SDT_RISCVSwapCSR, 80 [SDNPHasChain]>; 81 82def riscv_read_cycle_wide : SDNode<"RISCVISD::READ_CYCLE_WIDE", 83 SDT_RISCVReadCycleWide, 84 [SDNPHasChain, SDNPSideEffect]>; 85 86//===----------------------------------------------------------------------===// 87// Operand and SDNode transformation definitions. 88//===----------------------------------------------------------------------===// 89 90class ImmXLenAsmOperand<string prefix, string suffix = ""> : AsmOperandClass { 91 let Name = prefix # "ImmXLen" # suffix; 92 let RenderMethod = "addImmOperands"; 93 let DiagnosticType = !strconcat("Invalid", Name); 94} 95 96class ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass { 97 let Name = prefix # "Imm" # width # suffix; 98 let RenderMethod = "addImmOperands"; 99 let DiagnosticType = !strconcat("Invalid", Name); 100} 101 102def ImmZeroAsmOperand : AsmOperandClass { 103 let Name = "ImmZero"; 104 let RenderMethod = "addImmOperands"; 105 let DiagnosticType = !strconcat("Invalid", Name); 106} 107 108class SImmAsmOperand<int width, string suffix = ""> 109 : ImmAsmOperand<"S", width, suffix> { 110} 111 112class UImmAsmOperand<int width, string suffix = ""> 113 : ImmAsmOperand<"U", width, suffix> { 114} 115 116def FenceArg : AsmOperandClass { 117 let Name = "FenceArg"; 118 let RenderMethod = "addFenceArgOperands"; 119 let DiagnosticType = "InvalidFenceArg"; 120} 121 122def fencearg : Operand<XLenVT> { 123 let ParserMatchClass = FenceArg; 124 let PrintMethod = "printFenceArg"; 125 let DecoderMethod = "decodeUImmOperand<4>"; 126 let OperandType = "OPERAND_UIMM4"; 127 let OperandNamespace = "RISCVOp"; 128} 129 130def UImmLog2XLenAsmOperand : AsmOperandClass { 131 let Name = "UImmLog2XLen"; 132 let RenderMethod = "addImmOperands"; 133 let DiagnosticType = "InvalidUImmLog2XLen"; 134} 135 136def uimmlog2xlen : Operand<XLenVT>, ImmLeaf<XLenVT, [{ 137 if (Subtarget->is64Bit()) 138 return isUInt<6>(Imm); 139 return isUInt<5>(Imm); 140}]> { 141 let ParserMatchClass = UImmLog2XLenAsmOperand; 142 // TODO: should ensure invalid shamt is rejected when decoding. 143 let DecoderMethod = "decodeUImmOperand<6>"; 144 let MCOperandPredicate = [{ 145 int64_t Imm; 146 if (!MCOp.evaluateAsConstantImm(Imm)) 147 return false; 148 if (STI.getTargetTriple().isArch64Bit()) 149 return isUInt<6>(Imm); 150 return isUInt<5>(Imm); 151 }]; 152 let OperandType = "OPERAND_UIMMLOG2XLEN"; 153 let OperandNamespace = "RISCVOp"; 154} 155 156def uimm2 : Operand<XLenVT> { 157 let ParserMatchClass = UImmAsmOperand<2>; 158 let DecoderMethod = "decodeUImmOperand<2>"; 159 let OperandType = "OPERAND_UIMM2"; 160 let OperandNamespace = "RISCVOp"; 161} 162 163def uimm3 : Operand<XLenVT> { 164 let ParserMatchClass = UImmAsmOperand<3>; 165 let DecoderMethod = "decodeUImmOperand<3>"; 166 let OperandType = "OPERAND_UIMM3"; 167 let OperandNamespace = "RISCVOp"; 168} 169 170def uimm5 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]> { 171 let ParserMatchClass = UImmAsmOperand<5>; 172 let DecoderMethod = "decodeUImmOperand<5>"; 173 let OperandType = "OPERAND_UIMM5"; 174 let OperandNamespace = "RISCVOp"; 175} 176 177def InsnDirectiveOpcode : AsmOperandClass { 178 let Name = "InsnDirectiveOpcode"; 179 let ParserMethod = "parseInsnDirectiveOpcode"; 180 let RenderMethod = "addImmOperands"; 181 let PredicateMethod = "isImm"; 182} 183 184def uimm7_opcode : Operand<XLenVT> { 185 let ParserMatchClass = InsnDirectiveOpcode; 186 let DecoderMethod = "decodeUImmOperand<7>"; 187 let OperandType = "OPERAND_UIMM7"; 188 let OperandNamespace = "RISCVOp"; 189} 190 191def uimm7 : Operand<XLenVT> { 192 let ParserMatchClass = UImmAsmOperand<7>; 193 let DecoderMethod = "decodeUImmOperand<7>"; 194 let OperandType = "OPERAND_UIMM7"; 195 let OperandNamespace = "RISCVOp"; 196} 197 198def simm12 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isInt<12>(Imm);}]> { 199 let ParserMatchClass = SImmAsmOperand<12>; 200 let EncoderMethod = "getImmOpValue"; 201 let DecoderMethod = "decodeSImmOperand<12>"; 202 let MCOperandPredicate = [{ 203 int64_t Imm; 204 if (MCOp.evaluateAsConstantImm(Imm)) 205 return isInt<12>(Imm); 206 return MCOp.isBareSymbolRef(); 207 }]; 208 let OperandType = "OPERAND_SIMM12"; 209 let OperandNamespace = "RISCVOp"; 210} 211 212// A 13-bit signed immediate where the least significant bit is zero. 213def simm13_lsb0 : Operand<OtherVT> { 214 let ParserMatchClass = SImmAsmOperand<13, "Lsb0">; 215 let PrintMethod = "printBranchOperand"; 216 let EncoderMethod = "getImmOpValueAsr1"; 217 let DecoderMethod = "decodeSImmOperandAndLsl1<13>"; 218 let MCOperandPredicate = [{ 219 int64_t Imm; 220 if (MCOp.evaluateAsConstantImm(Imm)) 221 return isShiftedInt<12, 1>(Imm); 222 return MCOp.isBareSymbolRef(); 223 }]; 224 let OperandType = "OPERAND_PCREL"; 225} 226 227class UImm20Operand : Operand<XLenVT> { 228 let EncoderMethod = "getImmOpValue"; 229 let DecoderMethod = "decodeUImmOperand<20>"; 230 let MCOperandPredicate = [{ 231 int64_t Imm; 232 if (MCOp.evaluateAsConstantImm(Imm)) 233 return isUInt<20>(Imm); 234 return MCOp.isBareSymbolRef(); 235 }]; 236 let OperandType = "OPERAND_UIMM20"; 237 let OperandNamespace = "RISCVOp"; 238} 239 240def uimm20_lui : UImm20Operand { 241 let ParserMatchClass = UImmAsmOperand<20, "LUI">; 242} 243def uimm20_auipc : UImm20Operand { 244 let ParserMatchClass = UImmAsmOperand<20, "AUIPC">; 245} 246 247def Simm21Lsb0JALAsmOperand : SImmAsmOperand<21, "Lsb0JAL"> { 248 let ParserMethod = "parseJALOffset"; 249} 250 251// A 21-bit signed immediate where the least significant bit is zero. 252def simm21_lsb0_jal : Operand<OtherVT> { 253 let ParserMatchClass = Simm21Lsb0JALAsmOperand; 254 let PrintMethod = "printBranchOperand"; 255 let EncoderMethod = "getImmOpValueAsr1"; 256 let DecoderMethod = "decodeSImmOperandAndLsl1<21>"; 257 let MCOperandPredicate = [{ 258 int64_t Imm; 259 if (MCOp.evaluateAsConstantImm(Imm)) 260 return isShiftedInt<20, 1>(Imm); 261 return MCOp.isBareSymbolRef(); 262 }]; 263 let OperandType = "OPERAND_PCREL"; 264} 265 266def BareSymbol : AsmOperandClass { 267 let Name = "BareSymbol"; 268 let RenderMethod = "addImmOperands"; 269 let DiagnosticType = "InvalidBareSymbol"; 270 let ParserMethod = "parseBareSymbol"; 271} 272 273// A bare symbol. 274def bare_symbol : Operand<XLenVT> { 275 let ParserMatchClass = BareSymbol; 276} 277 278def CallSymbol : AsmOperandClass { 279 let Name = "CallSymbol"; 280 let RenderMethod = "addImmOperands"; 281 let DiagnosticType = "InvalidCallSymbol"; 282 let ParserMethod = "parseCallSymbol"; 283} 284 285// A bare symbol used in call/tail only. 286def call_symbol : Operand<XLenVT> { 287 let ParserMatchClass = CallSymbol; 288} 289 290def PseudoJumpSymbol : AsmOperandClass { 291 let Name = "PseudoJumpSymbol"; 292 let RenderMethod = "addImmOperands"; 293 let DiagnosticType = "InvalidPseudoJumpSymbol"; 294 let ParserMethod = "parsePseudoJumpSymbol"; 295} 296 297// A bare symbol used for pseudo jumps only. 298def pseudo_jump_symbol : Operand<XLenVT> { 299 let ParserMatchClass = PseudoJumpSymbol; 300} 301 302def TPRelAddSymbol : AsmOperandClass { 303 let Name = "TPRelAddSymbol"; 304 let RenderMethod = "addImmOperands"; 305 let DiagnosticType = "InvalidTPRelAddSymbol"; 306 let ParserMethod = "parseOperandWithModifier"; 307} 308 309// A bare symbol with the %tprel_add variant. 310def tprel_add_symbol : Operand<XLenVT> { 311 let ParserMatchClass = TPRelAddSymbol; 312} 313 314def CSRSystemRegister : AsmOperandClass { 315 let Name = "CSRSystemRegister"; 316 let ParserMethod = "parseCSRSystemRegister"; 317 let DiagnosticType = "InvalidCSRSystemRegister"; 318} 319 320def csr_sysreg : Operand<XLenVT> { 321 let ParserMatchClass = CSRSystemRegister; 322 let PrintMethod = "printCSRSystemRegister"; 323 let DecoderMethod = "decodeUImmOperand<12>"; 324 let OperandType = "OPERAND_UIMM12"; 325 let OperandNamespace = "RISCVOp"; 326} 327 328// A parameterized register class alternative to i32imm/i64imm from Target.td. 329def ixlenimm : Operand<XLenVT>; 330 331def ixlenimm_li : Operand<XLenVT> { 332 let ParserMatchClass = ImmXLenAsmOperand<"", "LI">; 333} 334 335// Standalone (codegen-only) immleaf patterns. 336 337// A 12-bit signed immediate plus one where the imm range will be -2047~2048. 338def simm12_plus1 : ImmLeaf<XLenVT, 339 [{return (isInt<12>(Imm) && Imm != -2048) || Imm == 2048;}]>; 340 341// A 6-bit constant greater than 32. 342def uimm6gt32 : ImmLeaf<XLenVT, [{ 343 return isUInt<6>(Imm) && Imm > 32; 344}]>; 345 346// Addressing modes. 347// Necessary because a frameindex can't be matched directly in a pattern. 348def AddrFI : ComplexPattern<iPTR, 1, "SelectAddrFI", [frameindex], []>; 349def BaseAddr : ComplexPattern<iPTR, 1, "SelectBaseAddr">; 350 351// Return the negation of an immediate value. 352def NegImm : SDNodeXForm<imm, [{ 353 return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N), 354 N->getValueType(0)); 355}]>; 356 357// Return an immediate value minus 32. 358def ImmSub32 : SDNodeXForm<imm, [{ 359 return CurDAG->getTargetConstant(N->getSExtValue() - 32, SDLoc(N), 360 N->getValueType(0)); 361}]>; 362 363// Return an immediate value plus 32. 364def ImmPlus32 : SDNodeXForm<imm, [{ 365 return CurDAG->getTargetConstant(N->getSExtValue() + 32, SDLoc(N), 366 N->getValueType(0)); 367}]>; 368 369// Return an immediate subtracted from XLen. 370def ImmSubFromXLen : SDNodeXForm<imm, [{ 371 uint64_t XLen = Subtarget->getXLen(); 372 return CurDAG->getTargetConstant(XLen - N->getZExtValue(), SDLoc(N), 373 N->getValueType(0)); 374}]>; 375 376// Return an immediate subtracted from 32. 377def ImmSubFrom32 : SDNodeXForm<imm, [{ 378 return CurDAG->getTargetConstant(32 - N->getZExtValue(), SDLoc(N), 379 N->getValueType(0)); 380}]>; 381 382// Check if (add r, imm) can be optimized to (ADDI (ADDI r, imm0), imm1), 383// in which imm = imm0 + imm1 and both imm0 and imm1 are simm12. 384def AddiPair : PatLeaf<(imm), [{ 385 if (!N->hasOneUse()) 386 return false; 387 // The immediate operand must be in range [-4096,-2049] or [2048,4094]. 388 int64_t Imm = N->getSExtValue(); 389 return (-4096 <= Imm && Imm <= -2049) || (2048 <= Imm && Imm <= 4094); 390}]>; 391 392// Return imm/2. 393def AddiPairImmA : SDNodeXForm<imm, [{ 394 return CurDAG->getTargetConstant(N->getSExtValue() / 2, SDLoc(N), 395 N->getValueType(0)); 396}]>; 397 398// Return imm - imm/2. 399def AddiPairImmB : SDNodeXForm<imm, [{ 400 int64_t Imm = N->getSExtValue(); 401 return CurDAG->getTargetConstant(Imm - Imm / 2, SDLoc(N), 402 N->getValueType(0)); 403}]>; 404 405def XLenSubTrailingOnes : SDNodeXForm<imm, [{ 406 uint64_t XLen = Subtarget->getXLen(); 407 uint64_t TrailingOnes = N->getAPIntValue().countTrailingOnes(); 408 return CurDAG->getTargetConstant(XLen - TrailingOnes, SDLoc(N), 409 N->getValueType(0)); 410}]>; 411 412// Checks if this mask is a non-empty sequence of ones starting at the 413// least significant bit with the remainder zero and exceeds simm12. 414def TrailingOnesMask : PatLeaf<(imm), [{ 415 if (!N->hasOneUse()) 416 return false; 417 return !isInt<12>(N->getSExtValue()) && isMask_64(N->getZExtValue()); 418}], XLenSubTrailingOnes>; 419 420//===----------------------------------------------------------------------===// 421// Instruction Formats 422//===----------------------------------------------------------------------===// 423 424include "RISCVInstrFormats.td" 425 426//===----------------------------------------------------------------------===// 427// Instruction Class Templates 428//===----------------------------------------------------------------------===// 429 430let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 431class BranchCC_rri<bits<3> funct3, string opcodestr> 432 : RVInstB<funct3, OPC_BRANCH, (outs), 433 (ins GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12), 434 opcodestr, "$rs1, $rs2, $imm12">, 435 Sched<[WriteJmp, ReadJmp, ReadJmp]> { 436 let isBranch = 1; 437 let isTerminator = 1; 438} 439 440let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in 441class Load_ri<bits<3> funct3, string opcodestr> 442 : RVInstI<funct3, OPC_LOAD, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), 443 opcodestr, "$rd, ${imm12}(${rs1})">; 444 445// Operands for stores are in the order srcreg, base, offset rather than 446// reflecting the order these fields are specified in the instruction 447// encoding. 448let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in 449class Store_rri<bits<3> funct3, string opcodestr> 450 : RVInstS<funct3, OPC_STORE, (outs), 451 (ins GPR:$rs2, GPR:$rs1, simm12:$imm12), 452 opcodestr, "$rs2, ${imm12}(${rs1})">; 453 454let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 455class ALU_ri<bits<3> funct3, string opcodestr> 456 : RVInstI<funct3, OPC_OP_IMM, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), 457 opcodestr, "$rd, $rs1, $imm12">, 458 Sched<[WriteIALU, ReadIALU]>; 459 460let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 461class Shift_ri<bits<5> imm11_7, bits<3> funct3, string opcodestr> 462 : RVInstIShift<imm11_7, funct3, OPC_OP_IMM, (outs GPR:$rd), 463 (ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr, 464 "$rd, $rs1, $shamt">, 465 Sched<[WriteShiftImm, ReadShiftImm]>; 466 467let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 468class ALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr> 469 : RVInstR<funct7, funct3, OPC_OP, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), 470 opcodestr, "$rd, $rs1, $rs2">; 471 472let hasNoSchedulingInfo = 1, 473 hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 474class CSR_ir<bits<3> funct3, string opcodestr> 475 : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), (ins csr_sysreg:$imm12, GPR:$rs1), 476 opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR, ReadCSR]>; 477 478let hasNoSchedulingInfo = 1, 479 hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 480class CSR_ii<bits<3> funct3, string opcodestr> 481 : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), 482 (ins csr_sysreg:$imm12, uimm5:$rs1), 483 opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR]>; 484 485let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 486class ShiftW_ri<bits<7> imm11_5, bits<3> funct3, string opcodestr> 487 : RVInstIShiftW<imm11_5, funct3, OPC_OP_IMM_32, (outs GPR:$rd), 488 (ins GPR:$rs1, uimm5:$shamt), opcodestr, 489 "$rd, $rs1, $shamt">, 490 Sched<[WriteShiftImm32, ReadShiftImm32]>; 491 492let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 493class ALUW_rr<bits<7> funct7, bits<3> funct3, string opcodestr> 494 : RVInstR<funct7, funct3, OPC_OP_32, (outs GPR:$rd), 495 (ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2">; 496 497let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 498class Priv<string opcodestr, bits<7> funct7> 499 : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2), 500 opcodestr, "">; 501 502//===----------------------------------------------------------------------===// 503// Instructions 504//===----------------------------------------------------------------------===// 505 506let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { 507let isReMaterializable = 1, isAsCheapAsAMove = 1 in 508def LUI : RVInstU<OPC_LUI, (outs GPR:$rd), (ins uimm20_lui:$imm20), 509 "lui", "$rd, $imm20">, Sched<[WriteIALU]>; 510 511def AUIPC : RVInstU<OPC_AUIPC, (outs GPR:$rd), (ins uimm20_auipc:$imm20), 512 "auipc", "$rd, $imm20">, Sched<[WriteIALU]>; 513 514let isCall = 1 in 515def JAL : RVInstJ<OPC_JAL, (outs GPR:$rd), (ins simm21_lsb0_jal:$imm20), 516 "jal", "$rd, $imm20">, Sched<[WriteJal]>; 517 518let isCall = 1 in 519def JALR : RVInstI<0b000, OPC_JALR, (outs GPR:$rd), 520 (ins GPR:$rs1, simm12:$imm12), 521 "jalr", "$rd, ${imm12}(${rs1})">, 522 Sched<[WriteJalr, ReadJalr]>; 523} // hasSideEffects = 0, mayLoad = 0, mayStore = 0 524 525def BEQ : BranchCC_rri<0b000, "beq">; 526def BNE : BranchCC_rri<0b001, "bne">; 527def BLT : BranchCC_rri<0b100, "blt">; 528def BGE : BranchCC_rri<0b101, "bge">; 529def BLTU : BranchCC_rri<0b110, "bltu">; 530def BGEU : BranchCC_rri<0b111, "bgeu">; 531 532def LB : Load_ri<0b000, "lb">, Sched<[WriteLDB, ReadMemBase]>; 533def LH : Load_ri<0b001, "lh">, Sched<[WriteLDH, ReadMemBase]>; 534def LW : Load_ri<0b010, "lw">, Sched<[WriteLDW, ReadMemBase]>; 535def LBU : Load_ri<0b100, "lbu">, Sched<[WriteLDB, ReadMemBase]>; 536def LHU : Load_ri<0b101, "lhu">, Sched<[WriteLDH, ReadMemBase]>; 537 538def SB : Store_rri<0b000, "sb">, Sched<[WriteSTB, ReadStoreData, ReadMemBase]>; 539def SH : Store_rri<0b001, "sh">, Sched<[WriteSTH, ReadStoreData, ReadMemBase]>; 540def SW : Store_rri<0b010, "sw">, Sched<[WriteSTW, ReadStoreData, ReadMemBase]>; 541 542// ADDI isn't always rematerializable, but isReMaterializable will be used as 543// a hint which is verified in isReallyTriviallyReMaterializable. 544let isReMaterializable = 1, isAsCheapAsAMove = 1 in 545def ADDI : ALU_ri<0b000, "addi">; 546 547def SLTI : ALU_ri<0b010, "slti">; 548def SLTIU : ALU_ri<0b011, "sltiu">; 549 550let isReMaterializable = 1, isAsCheapAsAMove = 1 in { 551def XORI : ALU_ri<0b100, "xori">; 552def ORI : ALU_ri<0b110, "ori">; 553} 554 555def ANDI : ALU_ri<0b111, "andi">; 556 557def SLLI : Shift_ri<0b00000, 0b001, "slli">; 558def SRLI : Shift_ri<0b00000, 0b101, "srli">; 559def SRAI : Shift_ri<0b01000, 0b101, "srai">; 560 561def ADD : ALU_rr<0b0000000, 0b000, "add">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 562def SUB : ALU_rr<0b0100000, 0b000, "sub">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 563def SLL : ALU_rr<0b0000000, 0b001, "sll">, Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; 564def SLT : ALU_rr<0b0000000, 0b010, "slt">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 565def SLTU : ALU_rr<0b0000000, 0b011, "sltu">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 566def XOR : ALU_rr<0b0000000, 0b100, "xor">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 567def SRL : ALU_rr<0b0000000, 0b101, "srl">, Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; 568def SRA : ALU_rr<0b0100000, 0b101, "sra">, Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; 569def OR : ALU_rr<0b0000000, 0b110, "or">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 570def AND : ALU_rr<0b0000000, 0b111, "and">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; 571 572let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in { 573def FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs), 574 (ins fencearg:$pred, fencearg:$succ), 575 "fence", "$pred, $succ">, Sched<[]> { 576 bits<4> pred; 577 bits<4> succ; 578 579 let rs1 = 0; 580 let rd = 0; 581 let imm12 = {0b0000,pred,succ}; 582} 583 584def FENCE_TSO : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins), "fence.tso", "">, Sched<[]> { 585 let rs1 = 0; 586 let rd = 0; 587 let imm12 = {0b1000,0b0011,0b0011}; 588} 589 590def FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), "fence.i", "">, Sched<[]> { 591 let rs1 = 0; 592 let rd = 0; 593 let imm12 = 0; 594} 595 596def ECALL : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ecall", "">, Sched<[WriteJmp]> { 597 let rs1 = 0; 598 let rd = 0; 599 let imm12 = 0; 600} 601 602def EBREAK : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ebreak", "">, 603 Sched<[]> { 604 let rs1 = 0; 605 let rd = 0; 606 let imm12 = 1; 607} 608 609// This is a de facto standard (as set by GNU binutils) 32-bit unimplemented 610// instruction (i.e., it should always trap, if your implementation has invalid 611// instruction traps). 612def UNIMP : RVInstI<0b001, OPC_SYSTEM, (outs), (ins), "unimp", "">, 613 Sched<[]> { 614 let rs1 = 0; 615 let rd = 0; 616 let imm12 = 0b110000000000; 617} 618} // hasSideEffects = 1, mayLoad = 0, mayStore = 0 619 620def CSRRW : CSR_ir<0b001, "csrrw">; 621def CSRRS : CSR_ir<0b010, "csrrs">; 622def CSRRC : CSR_ir<0b011, "csrrc">; 623 624def CSRRWI : CSR_ii<0b101, "csrrwi">; 625def CSRRSI : CSR_ii<0b110, "csrrsi">; 626def CSRRCI : CSR_ii<0b111, "csrrci">; 627 628/// RV64I instructions 629 630let Predicates = [IsRV64] in { 631def LWU : Load_ri<0b110, "lwu">, Sched<[WriteLDWU, ReadMemBase]>; 632def LD : Load_ri<0b011, "ld">, Sched<[WriteLDD, ReadMemBase]>; 633def SD : Store_rri<0b011, "sd">, Sched<[WriteSTD, ReadStoreData, ReadMemBase]>; 634 635let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in 636def ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd), 637 (ins GPR:$rs1, simm12:$imm12), 638 "addiw", "$rd, $rs1, $imm12">, 639 Sched<[WriteIALU32, ReadIALU32]>; 640 641def SLLIW : ShiftW_ri<0b0000000, 0b001, "slliw">; 642def SRLIW : ShiftW_ri<0b0000000, 0b101, "srliw">; 643def SRAIW : ShiftW_ri<0b0100000, 0b101, "sraiw">; 644 645def ADDW : ALUW_rr<0b0000000, 0b000, "addw">, 646 Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; 647def SUBW : ALUW_rr<0b0100000, 0b000, "subw">, 648 Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; 649def SLLW : ALUW_rr<0b0000000, 0b001, "sllw">, 650 Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; 651def SRLW : ALUW_rr<0b0000000, 0b101, "srlw">, 652 Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; 653def SRAW : ALUW_rr<0b0100000, 0b101, "sraw">, 654 Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>; 655} // Predicates = [IsRV64] 656 657//===----------------------------------------------------------------------===// 658// Privileged instructions 659//===----------------------------------------------------------------------===// 660 661let isBarrier = 1, isReturn = 1, isTerminator = 1 in { 662def URET : Priv<"uret", 0b0000000>, Sched<[]> { 663 let rd = 0; 664 let rs1 = 0; 665 let rs2 = 0b00010; 666} 667 668def SRET : Priv<"sret", 0b0001000>, Sched<[]> { 669 let rd = 0; 670 let rs1 = 0; 671 let rs2 = 0b00010; 672} 673 674def MRET : Priv<"mret", 0b0011000>, Sched<[]> { 675 let rd = 0; 676 let rs1 = 0; 677 let rs2 = 0b00010; 678} 679} // isBarrier = 1, isReturn = 1, isTerminator = 1 680 681def WFI : Priv<"wfi", 0b0001000>, Sched<[]> { 682 let rd = 0; 683 let rs1 = 0; 684 let rs2 = 0b00101; 685} 686 687let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in 688def SFENCE_VMA : RVInstR<0b0001001, 0b000, OPC_SYSTEM, (outs), 689 (ins GPR:$rs1, GPR:$rs2), 690 "sfence.vma", "$rs1, $rs2">, Sched<[]> { 691 let rd = 0; 692} 693 694//===----------------------------------------------------------------------===// 695// Debug instructions 696//===----------------------------------------------------------------------===// 697 698let isBarrier = 1, isReturn = 1, isTerminator = 1 in { 699def DRET : Priv<"dret", 0b0111101>, Sched<[]> { 700 let rd = 0; 701 let rs1 = 0; 702 let rs2 = 0b10010; 703} 704} // isBarrier = 1, isReturn = 1, isTerminator = 1 705 706//===----------------------------------------------------------------------===// 707// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20) 708//===----------------------------------------------------------------------===// 709 710def : InstAlias<"nop", (ADDI X0, X0, 0)>; 711 712// Note that the size is 32 because up to 8 32-bit instructions are needed to 713// generate an arbitrary 64-bit immediate. However, the size does not really 714// matter since PseudoLI is currently only used in the AsmParser where it gets 715// expanded to real instructions immediately. 716let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32, 717 isCodeGenOnly = 0, isAsmParserOnly = 1 in 718def PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm_li:$imm), [], 719 "li", "$rd, $imm">; 720 721def PseudoLB : PseudoLoad<"lb">; 722def PseudoLBU : PseudoLoad<"lbu">; 723def PseudoLH : PseudoLoad<"lh">; 724def PseudoLHU : PseudoLoad<"lhu">; 725def PseudoLW : PseudoLoad<"lw">; 726 727def PseudoSB : PseudoStore<"sb">; 728def PseudoSH : PseudoStore<"sh">; 729def PseudoSW : PseudoStore<"sw">; 730 731let Predicates = [IsRV64] in { 732def PseudoLWU : PseudoLoad<"lwu">; 733def PseudoLD : PseudoLoad<"ld">; 734def PseudoSD : PseudoStore<"sd">; 735} // Predicates = [IsRV64] 736 737def : InstAlias<"li $rd, $imm", (ADDI GPR:$rd, X0, simm12:$imm)>; 738def : InstAlias<"mv $rd, $rs", (ADDI GPR:$rd, GPR:$rs, 0)>; 739def : InstAlias<"not $rd, $rs", (XORI GPR:$rd, GPR:$rs, -1)>; 740def : InstAlias<"neg $rd, $rs", (SUB GPR:$rd, X0, GPR:$rs)>; 741 742let Predicates = [IsRV64] in { 743def : InstAlias<"negw $rd, $rs", (SUBW GPR:$rd, X0, GPR:$rs)>; 744def : InstAlias<"sext.w $rd, $rs", (ADDIW GPR:$rd, GPR:$rs, 0)>; 745} // Predicates = [IsRV64] 746 747def : InstAlias<"seqz $rd, $rs", (SLTIU GPR:$rd, GPR:$rs, 1)>; 748def : InstAlias<"snez $rd, $rs", (SLTU GPR:$rd, X0, GPR:$rs)>; 749def : InstAlias<"sltz $rd, $rs", (SLT GPR:$rd, GPR:$rs, X0)>; 750def : InstAlias<"sgtz $rd, $rs", (SLT GPR:$rd, X0, GPR:$rs)>; 751 752// sgt/sgtu are recognised by the GNU assembler but the canonical slt/sltu 753// form will always be printed. Therefore, set a zero weight. 754def : InstAlias<"sgt $rd, $rs, $rt", (SLT GPR:$rd, GPR:$rt, GPR:$rs), 0>; 755def : InstAlias<"sgtu $rd, $rs, $rt", (SLTU GPR:$rd, GPR:$rt, GPR:$rs), 0>; 756 757def : InstAlias<"beqz $rs, $offset", 758 (BEQ GPR:$rs, X0, simm13_lsb0:$offset)>; 759def : InstAlias<"bnez $rs, $offset", 760 (BNE GPR:$rs, X0, simm13_lsb0:$offset)>; 761def : InstAlias<"blez $rs, $offset", 762 (BGE X0, GPR:$rs, simm13_lsb0:$offset)>; 763def : InstAlias<"bgez $rs, $offset", 764 (BGE GPR:$rs, X0, simm13_lsb0:$offset)>; 765def : InstAlias<"bltz $rs, $offset", 766 (BLT GPR:$rs, X0, simm13_lsb0:$offset)>; 767def : InstAlias<"bgtz $rs, $offset", 768 (BLT X0, GPR:$rs, simm13_lsb0:$offset)>; 769 770// Always output the canonical mnemonic for the pseudo branch instructions. 771// The GNU tools emit the canonical mnemonic for the branch pseudo instructions 772// as well (e.g. "bgt" will be recognised by the assembler but never printed by 773// objdump). Match this behaviour by setting a zero weight. 774def : InstAlias<"bgt $rs, $rt, $offset", 775 (BLT GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 776def : InstAlias<"ble $rs, $rt, $offset", 777 (BGE GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 778def : InstAlias<"bgtu $rs, $rt, $offset", 779 (BLTU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 780def : InstAlias<"bleu $rs, $rt, $offset", 781 (BGEU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>; 782 783def : InstAlias<"j $offset", (JAL X0, simm21_lsb0_jal:$offset)>; 784def : InstAlias<"jal $offset", (JAL X1, simm21_lsb0_jal:$offset)>; 785 786// Non-zero offset aliases of "jalr" are the lowest weight, followed by the 787// two-register form, then the one-register forms and finally "ret". 788def : InstAlias<"jr $rs", (JALR X0, GPR:$rs, 0), 3>; 789def : InstAlias<"jr ${offset}(${rs})", (JALR X0, GPR:$rs, simm12:$offset)>; 790def : InstAlias<"jalr $rs", (JALR X1, GPR:$rs, 0), 3>; 791def : InstAlias<"jalr ${offset}(${rs})", (JALR X1, GPR:$rs, simm12:$offset)>; 792def : InstAlias<"jalr $rd, $rs", (JALR GPR:$rd, GPR:$rs, 0), 2>; 793def : InstAlias<"ret", (JALR X0, X1, 0), 4>; 794 795// Non-canonical forms for jump targets also accepted by the assembler. 796def : InstAlias<"jr $rs, $offset", (JALR X0, GPR:$rs, simm12:$offset), 0>; 797def : InstAlias<"jalr $rs, $offset", (JALR X1, GPR:$rs, simm12:$offset), 0>; 798def : InstAlias<"jalr $rd, $rs, $offset", (JALR GPR:$rd, GPR:$rs, simm12:$offset), 0>; 799 800def : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw 801 802def : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, INSTRET.Encoding, X0)>; 803def : InstAlias<"rdcycle $rd", (CSRRS GPR:$rd, CYCLE.Encoding, X0)>; 804def : InstAlias<"rdtime $rd", (CSRRS GPR:$rd, TIME.Encoding, X0)>; 805 806let Predicates = [IsRV32] in { 807def : InstAlias<"rdinstreth $rd", (CSRRS GPR:$rd, INSTRETH.Encoding, X0)>; 808def : InstAlias<"rdcycleh $rd", (CSRRS GPR:$rd, CYCLEH.Encoding, X0)>; 809def : InstAlias<"rdtimeh $rd", (CSRRS GPR:$rd, TIMEH.Encoding, X0)>; 810} // Predicates = [IsRV32] 811 812def : InstAlias<"csrr $rd, $csr", (CSRRS GPR:$rd, csr_sysreg:$csr, X0)>; 813def : InstAlias<"csrw $csr, $rs", (CSRRW X0, csr_sysreg:$csr, GPR:$rs)>; 814def : InstAlias<"csrs $csr, $rs", (CSRRS X0, csr_sysreg:$csr, GPR:$rs)>; 815def : InstAlias<"csrc $csr, $rs", (CSRRC X0, csr_sysreg:$csr, GPR:$rs)>; 816 817def : InstAlias<"csrwi $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>; 818def : InstAlias<"csrsi $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>; 819def : InstAlias<"csrci $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>; 820 821let EmitPriority = 0 in { 822def : InstAlias<"csrw $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>; 823def : InstAlias<"csrs $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>; 824def : InstAlias<"csrc $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>; 825 826def : InstAlias<"csrrw $rd, $csr, $imm", (CSRRWI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 827def : InstAlias<"csrrs $rd, $csr, $imm", (CSRRSI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 828def : InstAlias<"csrrc $rd, $csr, $imm", (CSRRCI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>; 829} 830 831def : InstAlias<"sfence.vma", (SFENCE_VMA X0, X0)>; 832def : InstAlias<"sfence.vma $rs", (SFENCE_VMA GPR:$rs, X0)>; 833 834let EmitPriority = 0 in { 835def : InstAlias<"lb $rd, (${rs1})", 836 (LB GPR:$rd, GPR:$rs1, 0)>; 837def : InstAlias<"lh $rd, (${rs1})", 838 (LH GPR:$rd, GPR:$rs1, 0)>; 839def : InstAlias<"lw $rd, (${rs1})", 840 (LW GPR:$rd, GPR:$rs1, 0)>; 841def : InstAlias<"lbu $rd, (${rs1})", 842 (LBU GPR:$rd, GPR:$rs1, 0)>; 843def : InstAlias<"lhu $rd, (${rs1})", 844 (LHU GPR:$rd, GPR:$rs1, 0)>; 845 846def : InstAlias<"sb $rs2, (${rs1})", 847 (SB GPR:$rs2, GPR:$rs1, 0)>; 848def : InstAlias<"sh $rs2, (${rs1})", 849 (SH GPR:$rs2, GPR:$rs1, 0)>; 850def : InstAlias<"sw $rs2, (${rs1})", 851 (SW GPR:$rs2, GPR:$rs1, 0)>; 852 853def : InstAlias<"add $rd, $rs1, $imm12", 854 (ADDI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 855def : InstAlias<"and $rd, $rs1, $imm12", 856 (ANDI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 857def : InstAlias<"xor $rd, $rs1, $imm12", 858 (XORI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 859def : InstAlias<"or $rd, $rs1, $imm12", 860 (ORI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 861def : InstAlias<"sll $rd, $rs1, $shamt", 862 (SLLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 863def : InstAlias<"srl $rd, $rs1, $shamt", 864 (SRLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 865def : InstAlias<"sra $rd, $rs1, $shamt", 866 (SRAI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>; 867let Predicates = [IsRV64] in { 868def : InstAlias<"lwu $rd, (${rs1})", 869 (LWU GPR:$rd, GPR:$rs1, 0)>; 870def : InstAlias<"ld $rd, (${rs1})", 871 (LD GPR:$rd, GPR:$rs1, 0)>; 872def : InstAlias<"sd $rs2, (${rs1})", 873 (SD GPR:$rs2, GPR:$rs1, 0)>; 874 875def : InstAlias<"addw $rd, $rs1, $imm12", 876 (ADDIW GPR:$rd, GPR:$rs1, simm12:$imm12)>; 877def : InstAlias<"sllw $rd, $rs1, $shamt", 878 (SLLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 879def : InstAlias<"srlw $rd, $rs1, $shamt", 880 (SRLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 881def : InstAlias<"sraw $rd, $rs1, $shamt", 882 (SRAIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>; 883} // Predicates = [IsRV64] 884def : InstAlias<"slt $rd, $rs1, $imm12", 885 (SLTI GPR:$rd, GPR:$rs1, simm12:$imm12)>; 886def : InstAlias<"sltu $rd, $rs1, $imm12", 887 (SLTIU GPR:$rd, GPR:$rs1, simm12:$imm12)>; 888} 889 890def : MnemonicAlias<"move", "mv">; 891 892// The SCALL and SBREAK instructions wererenamed to ECALL and EBREAK in 893// version 2.1 of the user-level ISA. Like the GNU toolchain, we still accept 894// the old name for backwards compatibility. 895def : MnemonicAlias<"scall", "ecall">; 896def : MnemonicAlias<"sbreak", "ebreak">; 897 898// This alias was added to the spec in December 2020. Don't print it by default 899// to allow assembly we print to be compatible with versions of GNU assembler 900// that don't support this alias. 901def : InstAlias<"zext.b $rd, $rs", (ANDI GPR:$rd, GPR:$rs, 0xFF), 0>; 902 903//===----------------------------------------------------------------------===// 904// .insn directive instructions 905//===----------------------------------------------------------------------===// 906 907// isCodeGenOnly = 1 to hide them from the tablegened assembly parser. 908let isCodeGenOnly = 1, hasSideEffects = 1, mayLoad = 1, mayStore = 1, 909 hasNoSchedulingInfo = 1 in { 910def InsnR : DirectiveInsnR<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$funct3, 911 uimm7:$funct7, AnyReg:$rs1, 912 AnyReg:$rs2), 913 "$opcode, $funct3, $funct7, $rd, $rs1, $rs2">; 914def InsnR4 : DirectiveInsnR4<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 915 uimm3:$funct3, 916 uimm2:$funct2, 917 AnyReg:$rs1, AnyReg:$rs2, 918 AnyReg:$rs3), 919 "$opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3">; 920def InsnI : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$funct3, 921 AnyReg:$rs1, simm12:$imm12), 922 "$opcode, $funct3, $rd, $rs1, $imm12">; 923def InsnI_Mem : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 924 uimm3:$funct3, 925 AnyReg:$rs1, 926 simm12:$imm12), 927 "$opcode, $funct3, $rd, ${imm12}(${rs1})">; 928def InsnB : DirectiveInsnB<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3, 929 AnyReg:$rs1, AnyReg:$rs2, 930 simm13_lsb0:$imm12), 931 "$opcode, $funct3, $rs1, $rs2, $imm12">; 932def InsnU : DirectiveInsnU<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 933 uimm20_lui:$imm20), 934 "$opcode, $rd, $imm20">; 935def InsnJ : DirectiveInsnJ<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, 936 simm21_lsb0_jal:$imm20), 937 "$opcode, $rd, $imm20">; 938def InsnS : DirectiveInsnS<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3, 939 AnyReg:$rs2, AnyReg:$rs1, 940 simm12:$imm12), 941 "$opcode, $funct3, $rs2, ${imm12}(${rs1})">; 942} 943 944// Use InstAliases to match these so that we can combine the insn and format 945// into a mnemonic to use as the key for the tablegened asm matcher table. The 946// parser will take care of creating these fake mnemonics and will only do it 947// for known formats. 948let EmitPriority = 0 in { 949def : InstAlias<".insn_r $opcode, $funct3, $funct7, $rd, $rs1, $rs2", 950 (InsnR AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm7:$funct7, 951 AnyReg:$rs1, AnyReg:$rs2)>; 952// Accept 4 register form of ".insn r" as alias for ".insn r4". 953def : InstAlias<".insn_r $opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3", 954 (InsnR4 AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm2:$funct2, 955 AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>; 956def : InstAlias<".insn_r4 $opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3", 957 (InsnR4 AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm2:$funct2, 958 AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>; 959def : InstAlias<".insn_i $opcode, $funct3, $rd, $rs1, $imm12", 960 (InsnI AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1, 961 simm12:$imm12)>; 962def : InstAlias<".insn_i $opcode, $funct3, $rd, ${imm12}(${rs1})", 963 (InsnI_Mem AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, 964 AnyReg:$rs1, simm12:$imm12)>; 965def : InstAlias<".insn_b $opcode, $funct3, $rs1, $rs2, $imm12", 966 (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1, 967 AnyReg:$rs2, simm13_lsb0:$imm12)>; 968// Accept sb as an alias for b. 969def : InstAlias<".insn_sb $opcode, $funct3, $rs1, $rs2, $imm12", 970 (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1, 971 AnyReg:$rs2, simm13_lsb0:$imm12)>; 972def : InstAlias<".insn_u $opcode, $rd, $imm20", 973 (InsnU AnyReg:$rd, uimm7_opcode:$opcode, uimm20_lui:$imm20)>; 974def : InstAlias<".insn_j $opcode, $rd, $imm20", 975 (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>; 976// Accept uj as an alias for j. 977def : InstAlias<".insn_uj $opcode, $rd, $imm20", 978 (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>; 979def : InstAlias<".insn_s $opcode, $funct3, $rs2, ${imm12}(${rs1})", 980 (InsnS uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs2, 981 AnyReg:$rs1, simm12:$imm12)>; 982} 983 984//===----------------------------------------------------------------------===// 985// Pseudo-instructions and codegen patterns 986// 987// Naming convention: For 'generic' pattern classes, we use the naming 988// convention PatTy1Ty2. For pattern classes which offer a more complex 989// expansion, prefix the class name, e.g. BccPat. 990//===----------------------------------------------------------------------===// 991 992/// Generic pattern classes 993 994class PatGpr<SDPatternOperator OpNode, RVInst Inst> 995 : Pat<(OpNode GPR:$rs1), (Inst GPR:$rs1)>; 996class PatGprGpr<SDPatternOperator OpNode, RVInst Inst> 997 : Pat<(OpNode GPR:$rs1, GPR:$rs2), (Inst GPR:$rs1, GPR:$rs2)>; 998 999class PatGprImm<SDPatternOperator OpNode, RVInst Inst, ImmLeaf ImmType> 1000 : Pat<(XLenVT (OpNode (XLenVT GPR:$rs1), ImmType:$imm)), 1001 (Inst GPR:$rs1, ImmType:$imm)>; 1002class PatGprSimm12<SDPatternOperator OpNode, RVInstI Inst> 1003 : PatGprImm<OpNode, Inst, simm12>; 1004class PatGprUimmLog2XLen<SDPatternOperator OpNode, RVInstIShift Inst> 1005 : PatGprImm<OpNode, Inst, uimmlog2xlen>; 1006 1007/// Predicates 1008 1009def IsOrAdd: PatFrag<(ops node:$A, node:$B), (or node:$A, node:$B), [{ 1010 return isOrEquivalentToAdd(N); 1011}]>; 1012def assertsexti32 : PatFrag<(ops node:$src), (assertsext node:$src), [{ 1013 return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32); 1014}]>; 1015def sexti32 : ComplexPattern<i64, 1, "selectSExti32">; 1016def assertzexti32 : PatFrag<(ops node:$src), (assertzext node:$src), [{ 1017 return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32); 1018}]>; 1019def zexti32 : ComplexPattern<i64, 1, "selectZExti32">; 1020 1021def add_oneuse : PatFrag<(ops node:$A, node:$B), (add node:$A, node:$B), [{ 1022 return N->hasOneUse(); 1023}]>; 1024 1025def mul_oneuse : PatFrag<(ops node:$A, node:$B), (mul node:$A, node:$B), [{ 1026 return N->hasOneUse(); 1027}]>; 1028 1029def mul_const_oneuse : PatFrag<(ops node:$A, node:$B), 1030 (mul node:$A, node:$B), [{ 1031 if (auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1))) 1032 if (N1C->hasOneUse()) 1033 return true; 1034 return false; 1035}]>; 1036 1037def sext_oneuse : PatFrag<(ops node:$A), (sext node:$A), [{ 1038 return N->hasOneUse(); 1039}]>; 1040 1041def zext_oneuse : PatFrag<(ops node:$A), (zext node:$A), [{ 1042 return N->hasOneUse(); 1043}]>; 1044 1045def anyext_oneuse : PatFrag<(ops node:$A), (anyext node:$A), [{ 1046 return N->hasOneUse(); 1047}]>; 1048 1049def fpext_oneuse : PatFrag<(ops node:$A), 1050 (any_fpextend node:$A), [{ 1051 return N->hasOneUse(); 1052}]>; 1053 1054/// Simple arithmetic operations 1055 1056def : PatGprGpr<add, ADD>; 1057def : PatGprSimm12<add, ADDI>; 1058def : PatGprGpr<sub, SUB>; 1059def : PatGprGpr<or, OR>; 1060def : PatGprSimm12<or, ORI>; 1061def : PatGprGpr<and, AND>; 1062def : PatGprSimm12<and, ANDI>; 1063def : PatGprGpr<xor, XOR>; 1064def : PatGprSimm12<xor, XORI>; 1065def : PatGprUimmLog2XLen<shl, SLLI>; 1066def : PatGprUimmLog2XLen<srl, SRLI>; 1067def : PatGprUimmLog2XLen<sra, SRAI>; 1068 1069// AND with trailing ones mask exceeding simm12. 1070def : Pat<(XLenVT (and GPR:$rs, TrailingOnesMask:$mask)), 1071 (SRLI (SLLI $rs, TrailingOnesMask:$mask), TrailingOnesMask:$mask)>; 1072 1073// Match both a plain shift and one where the shift amount is masked (this is 1074// typically introduced when the legalizer promotes the shift amount and 1075// zero-extends it). For RISC-V, the mask is unnecessary as shifts in the base 1076// ISA only read the least significant 5 bits (RV32I) or 6 bits (RV64I). 1077def shiftMaskXLen : ComplexPattern<XLenVT, 1, "selectShiftMaskXLen", [], [], 0>; 1078def shiftMask32 : ComplexPattern<i64, 1, "selectShiftMask32", [], [], 0>; 1079 1080class shiftop<SDPatternOperator operator> 1081 : PatFrag<(ops node:$val, node:$count), 1082 (operator node:$val, (XLenVT (shiftMaskXLen node:$count)))>; 1083class shiftopw<SDPatternOperator operator> 1084 : PatFrag<(ops node:$val, node:$count), 1085 (operator node:$val, (i64 (shiftMask32 node:$count)))>; 1086 1087def : PatGprGpr<shiftop<shl>, SLL>; 1088def : PatGprGpr<shiftop<srl>, SRL>; 1089def : PatGprGpr<shiftop<sra>, SRA>; 1090 1091// This is a special case of the ADD instruction used to facilitate the use of a 1092// fourth operand to emit a relocation on a symbol relating to this instruction. 1093// The relocation does not affect any bits of the instruction itself but is used 1094// as a hint to the linker. 1095let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in 1096def PseudoAddTPRel : Pseudo<(outs GPR:$rd), 1097 (ins GPR:$rs1, GPR:$rs2, tprel_add_symbol:$src), [], 1098 "add", "$rd, $rs1, $rs2, $src">; 1099 1100/// FrameIndex calculations 1101 1102def : Pat<(add (XLenVT AddrFI:$Rs), simm12:$imm12), 1103 (ADDI (XLenVT AddrFI:$Rs), simm12:$imm12)>; 1104def : Pat<(IsOrAdd (XLenVT AddrFI:$Rs), simm12:$imm12), 1105 (ADDI (XLenVT AddrFI:$Rs), simm12:$imm12)>; 1106 1107/// Setcc 1108 1109def : PatGprGpr<setlt, SLT>; 1110def : PatGprSimm12<setlt, SLTI>; 1111def : PatGprGpr<setult, SLTU>; 1112def : PatGprSimm12<setult, SLTIU>; 1113 1114// Define pattern expansions for setcc operations that aren't directly 1115// handled by a RISC-V instruction. 1116def : Pat<(seteq GPR:$rs1, 0), (SLTIU GPR:$rs1, 1)>; 1117def : Pat<(seteq GPR:$rs1, GPR:$rs2), (SLTIU (XOR GPR:$rs1, GPR:$rs2), 1)>; 1118def : Pat<(seteq GPR:$rs1, simm12_plus1:$imm12), 1119 (SLTIU (ADDI GPR:$rs1, (NegImm simm12_plus1:$imm12)), 1)>; 1120def : Pat<(setne GPR:$rs1, 0), (SLTU X0, GPR:$rs1)>; 1121def : Pat<(setne GPR:$rs1, GPR:$rs2), (SLTU X0, (XOR GPR:$rs1, GPR:$rs2))>; 1122def : Pat<(setne GPR:$rs1, simm12_plus1:$imm12), 1123 (SLTU X0, (ADDI GPR:$rs1, (NegImm simm12_plus1:$imm12)))>; 1124def : Pat<(setugt GPR:$rs1, GPR:$rs2), (SLTU GPR:$rs2, GPR:$rs1)>; 1125def : Pat<(setuge GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs1, GPR:$rs2), 1)>; 1126def : Pat<(setule GPR:$rs1, GPR:$rs2), (XORI (SLTU GPR:$rs2, GPR:$rs1), 1)>; 1127def : Pat<(setgt GPR:$rs1, GPR:$rs2), (SLT GPR:$rs2, GPR:$rs1)>; 1128def : Pat<(setge GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs1, GPR:$rs2), 1)>; 1129def : Pat<(setle GPR:$rs1, GPR:$rs2), (XORI (SLT GPR:$rs2, GPR:$rs1), 1)>; 1130 1131def IntCCtoRISCVCC : SDNodeXForm<riscv_selectcc, [{ 1132 ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get(); 1133 RISCVCC::CondCode BrCC = getRISCVCCForIntCC(CC); 1134 return CurDAG->getTargetConstant(BrCC, SDLoc(N), Subtarget->getXLenVT()); 1135}]>; 1136 1137def riscv_selectcc_frag : PatFrag<(ops node:$lhs, node:$rhs, node:$cc, 1138 node:$truev, node:$falsev), 1139 (riscv_selectcc node:$lhs, node:$rhs, 1140 node:$cc, node:$truev, 1141 node:$falsev), [{}], 1142 IntCCtoRISCVCC>; 1143 1144let usesCustomInserter = 1 in 1145class SelectCC_rrirr<RegisterClass valty, RegisterClass cmpty> 1146 : Pseudo<(outs valty:$dst), 1147 (ins cmpty:$lhs, cmpty:$rhs, ixlenimm:$imm, 1148 valty:$truev, valty:$falsev), 1149 [(set valty:$dst, 1150 (riscv_selectcc_frag:$imm cmpty:$lhs, cmpty:$rhs, cond, 1151 valty:$truev, valty:$falsev))]>; 1152 1153def Select_GPR_Using_CC_GPR : SelectCC_rrirr<GPR, GPR>; 1154 1155/// Branches and jumps 1156 1157// Match `riscv_brcc` and lower to the appropriate RISC-V branch instruction. 1158class BccPat<CondCode Cond, RVInstB Inst> 1159 : Pat<(riscv_brcc GPR:$rs1, GPR:$rs2, Cond, bb:$imm12), 1160 (Inst GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12)>; 1161 1162def : BccPat<SETEQ, BEQ>; 1163def : BccPat<SETNE, BNE>; 1164def : BccPat<SETLT, BLT>; 1165def : BccPat<SETGE, BGE>; 1166def : BccPat<SETULT, BLTU>; 1167def : BccPat<SETUGE, BGEU>; 1168 1169let isBarrier = 1, isBranch = 1, isTerminator = 1 in 1170def PseudoBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>, 1171 PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>; 1172 1173let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in 1174def PseudoBRIND : Pseudo<(outs), (ins GPRJALR:$rs1, simm12:$imm12), []>, 1175 PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; 1176 1177def : Pat<(brind GPRJALR:$rs1), (PseudoBRIND GPRJALR:$rs1, 0)>; 1178def : Pat<(brind (add GPRJALR:$rs1, simm12:$imm12)), 1179 (PseudoBRIND GPRJALR:$rs1, simm12:$imm12)>; 1180 1181// PseudoCALLReg is a generic pseudo instruction for calls which will eventually 1182// expand to auipc and jalr while encoding, with any given register used as the 1183// destination. 1184// Define AsmString to print "call" when compile with -S flag. 1185// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction. 1186let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, Size = 8, hasSideEffects = 0, 1187 mayStore = 0, mayLoad = 0 in 1188def PseudoCALLReg : Pseudo<(outs GPR:$rd), (ins call_symbol:$func), []> { 1189 let AsmString = "call\t$rd, $func"; 1190} 1191 1192// PseudoCALL is a pseudo instruction which will eventually expand to auipc 1193// and jalr while encoding. This is desirable, as an auipc+jalr pair with 1194// R_RISCV_CALL and R_RISCV_RELAX relocations can be be relaxed by the linker 1195// if the offset fits in a signed 21-bit immediate. 1196// Define AsmString to print "call" when compile with -S flag. 1197// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction. 1198let isCall = 1, Defs = [X1], isCodeGenOnly = 0, Size = 8 in 1199def PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), []> { 1200 let AsmString = "call\t$func"; 1201} 1202 1203def : Pat<(riscv_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>; 1204def : Pat<(riscv_call texternalsym:$func), (PseudoCALL texternalsym:$func)>; 1205 1206def : Pat<(riscv_uret_flag), (URET X0, X0)>; 1207def : Pat<(riscv_sret_flag), (SRET X0, X0)>; 1208def : Pat<(riscv_mret_flag), (MRET X0, X0)>; 1209 1210let isCall = 1, Defs = [X1] in 1211def PseudoCALLIndirect : Pseudo<(outs), (ins GPRJALR:$rs1), 1212 [(riscv_call GPRJALR:$rs1)]>, 1213 PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>; 1214 1215let isBarrier = 1, isReturn = 1, isTerminator = 1 in 1216def PseudoRET : Pseudo<(outs), (ins), [(riscv_ret_flag)]>, 1217 PseudoInstExpansion<(JALR X0, X1, 0)>; 1218 1219// PseudoTAIL is a pseudo instruction similar to PseudoCALL and will eventually 1220// expand to auipc and jalr while encoding. 1221// Define AsmString to print "tail" when compile with -S flag. 1222let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2], 1223 Size = 8, isCodeGenOnly = 0 in 1224def PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), []> { 1225 let AsmString = "tail\t$dst"; 1226} 1227 1228let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in 1229def PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1), 1230 [(riscv_tail GPRTC:$rs1)]>, 1231 PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>; 1232 1233def : Pat<(riscv_tail (iPTR tglobaladdr:$dst)), 1234 (PseudoTAIL texternalsym:$dst)>; 1235def : Pat<(riscv_tail (iPTR texternalsym:$dst)), 1236 (PseudoTAIL texternalsym:$dst)>; 1237 1238let isCall = 0, isBarrier = 1, isBranch = 1, isTerminator = 1, Size = 8, 1239 isCodeGenOnly = 0, hasSideEffects = 0, mayStore = 0, mayLoad = 0 in 1240def PseudoJump : Pseudo<(outs GPR:$rd), (ins pseudo_jump_symbol:$target), []> { 1241 let AsmString = "jump\t$target, $rd"; 1242} 1243 1244let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0, 1245 isAsmParserOnly = 1 in 1246def PseudoLLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1247 "lla", "$dst, $src">; 1248 1249let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0, 1250 isAsmParserOnly = 1 in 1251def PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1252 "la", "$dst, $src">; 1253 1254let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0, 1255 isAsmParserOnly = 1 in 1256def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1257 "la.tls.ie", "$dst, $src">; 1258 1259let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0, 1260 isAsmParserOnly = 1 in 1261def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], 1262 "la.tls.gd", "$dst, $src">; 1263 1264 1265/// Sign/Zero Extends 1266 1267// There are single-instruction versions of these in Zbb, so disable these 1268// Pseudos if that extension is present. 1269let hasSideEffects = 0, mayLoad = 0, 1270 mayStore = 0, isCodeGenOnly = 0, isAsmParserOnly = 1 in { 1271def PseudoSEXT_B : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.b", "$rd, $rs">; 1272def PseudoSEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.h", "$rd, $rs">; 1273// rv64's sext.w is defined above, using InstAlias<"sext.w ... 1274// zext.b is defined above, using InstAlias<"zext.b ... 1275def PseudoZEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.h", "$rd, $rs">; 1276} // hasSideEffects = 0, ... 1277 1278let Predicates = [IsRV64], hasSideEffects = 0, mayLoad = 0, mayStore = 0, 1279 isCodeGenOnly = 0, isAsmParserOnly = 1 in { 1280def PseudoZEXT_W : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.w", "$rd, $rs">; 1281} // Predicates = [IsRV64], ... 1282 1283/// Loads 1284 1285multiclass LdPat<PatFrag LoadOp, RVInst Inst, ValueType vt = XLenVT> { 1286 def : Pat<(vt (LoadOp BaseAddr:$rs1)), (Inst BaseAddr:$rs1, 0)>; 1287 def : Pat<(vt (LoadOp (add BaseAddr:$rs1, simm12:$imm12))), 1288 (Inst BaseAddr:$rs1, simm12:$imm12)>; 1289 def : Pat<(vt (LoadOp (IsOrAdd AddrFI:$rs1, simm12:$imm12))), 1290 (Inst AddrFI:$rs1, simm12:$imm12)>; 1291} 1292 1293defm : LdPat<sextloadi8, LB>; 1294defm : LdPat<extloadi8, LB>; 1295defm : LdPat<sextloadi16, LH>; 1296defm : LdPat<extloadi16, LH>; 1297defm : LdPat<load, LW, i32>, Requires<[IsRV32]>; 1298defm : LdPat<zextloadi8, LBU>; 1299defm : LdPat<zextloadi16, LHU>; 1300 1301/// Stores 1302 1303multiclass StPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy, 1304 ValueType vt> { 1305 def : Pat<(StoreOp (vt StTy:$rs2), BaseAddr:$rs1), 1306 (Inst StTy:$rs2, BaseAddr:$rs1, 0)>; 1307 def : Pat<(StoreOp (vt StTy:$rs2), (add BaseAddr:$rs1, simm12:$imm12)), 1308 (Inst StTy:$rs2, BaseAddr:$rs1, simm12:$imm12)>; 1309 def : Pat<(StoreOp (vt StTy:$rs2), (IsOrAdd AddrFI:$rs1, simm12:$imm12)), 1310 (Inst StTy:$rs2, AddrFI:$rs1, simm12:$imm12)>; 1311} 1312 1313defm : StPat<truncstorei8, SB, GPR, XLenVT>; 1314defm : StPat<truncstorei16, SH, GPR, XLenVT>; 1315defm : StPat<store, SW, GPR, i32>, Requires<[IsRV32]>; 1316 1317/// Fences 1318 1319// Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set 1320// Manual: Volume I. 1321 1322// fence acquire -> fence r, rw 1323def : Pat<(atomic_fence (XLenVT 4), (timm)), (FENCE 0b10, 0b11)>; 1324// fence release -> fence rw, w 1325def : Pat<(atomic_fence (XLenVT 5), (timm)), (FENCE 0b11, 0b1)>; 1326// fence acq_rel -> fence.tso 1327def : Pat<(atomic_fence (XLenVT 6), (timm)), (FENCE_TSO)>; 1328// fence seq_cst -> fence rw, rw 1329def : Pat<(atomic_fence (XLenVT 7), (timm)), (FENCE 0b11, 0b11)>; 1330 1331// Lowering for atomic load and store is defined in RISCVInstrInfoA.td. 1332// Although these are lowered to fence+load/store instructions defined in the 1333// base RV32I/RV64I ISA, this lowering is only used when the A extension is 1334// present. This is necessary as it isn't valid to mix __atomic_* libcalls 1335// with inline atomic operations for the same object. 1336 1337/// Access to system registers 1338 1339// Helpers for defining specific operations. They are defined for each system 1340// register separately. Side effect is not used because dependencies are 1341// expressed via use-def properties. 1342 1343class ReadSysReg<SysReg SR, list<Register> Regs> 1344 : Pseudo<(outs GPR:$rd), (ins), 1345 [(set GPR:$rd, (riscv_read_csr (XLenVT SR.Encoding)))]>, 1346 PseudoInstExpansion<(CSRRS GPR:$rd, SR.Encoding, X0)> { 1347 let hasSideEffects = 0; 1348 let Uses = Regs; 1349} 1350 1351class WriteSysReg<SysReg SR, list<Register> Regs> 1352 : Pseudo<(outs), (ins GPR:$val), 1353 [(riscv_write_csr (XLenVT SR.Encoding), GPR:$val)]>, 1354 PseudoInstExpansion<(CSRRW X0, SR.Encoding, GPR:$val)> { 1355 let hasSideEffects = 0; 1356 let Defs = Regs; 1357} 1358 1359class WriteSysRegImm<SysReg SR, list<Register> Regs> 1360 : Pseudo<(outs), (ins uimm5:$val), 1361 [(riscv_write_csr (XLenVT SR.Encoding), uimm5:$val)]>, 1362 PseudoInstExpansion<(CSRRWI X0, SR.Encoding, uimm5:$val)> { 1363 let hasSideEffects = 0; 1364 let Defs = Regs; 1365} 1366 1367class SwapSysReg<SysReg SR, list<Register> Regs> 1368 : Pseudo<(outs GPR:$rd), (ins GPR:$val), 1369 [(set GPR:$rd, (riscv_swap_csr (XLenVT SR.Encoding), GPR:$val))]>, 1370 PseudoInstExpansion<(CSRRW GPR:$rd, SR.Encoding, GPR:$val)> { 1371 let hasSideEffects = 0; 1372 let Uses = Regs; 1373 let Defs = Regs; 1374} 1375 1376class SwapSysRegImm<SysReg SR, list<Register> Regs> 1377 : Pseudo<(outs GPR:$rd), (ins uimm5:$val), 1378 [(set GPR:$rd, (riscv_swap_csr (XLenVT SR.Encoding), uimm5:$val))]>, 1379 PseudoInstExpansion<(CSRRWI GPR:$rd, SR.Encoding, uimm5:$val)> { 1380 let hasSideEffects = 0; 1381 let Uses = Regs; 1382 let Defs = Regs; 1383} 1384 1385def ReadFRM : ReadSysReg<SysRegFRM, [FRM]>; 1386def WriteFRM : WriteSysReg<SysRegFRM, [FRM]>; 1387def WriteFRMImm : WriteSysRegImm<SysRegFRM, [FRM]>; 1388 1389let hasSideEffects = true in { 1390def ReadFFLAGS : ReadSysReg<SysRegFFLAGS, [FFLAGS]>; 1391def WriteFFLAGS : WriteSysReg<SysRegFFLAGS, [FFLAGS]>; 1392} 1393/// Other pseudo-instructions 1394 1395// Pessimistically assume the stack pointer will be clobbered 1396let Defs = [X2], Uses = [X2] in { 1397def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 1398 [(callseq_start timm:$amt1, timm:$amt2)]>; 1399def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 1400 [(callseq_end timm:$amt1, timm:$amt2)]>; 1401} // Defs = [X2], Uses = [X2] 1402 1403/// RV64 patterns 1404 1405let Predicates = [IsRV64, NotHasStdExtZba] in { 1406def : Pat<(i64 (and GPR:$rs1, 0xffffffff)), (SRLI (SLLI GPR:$rs1, 32), 32)>; 1407 1408// If we're shifting a 32-bit zero extended value left by 0-31 bits, use 2 1409// shifts instead of 3. This can occur when unsigned is used to index an array. 1410def : Pat<(i64 (shl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)), 1411 (SRLI (SLLI GPR:$rs1, 32), (ImmSubFrom32 uimm5:$shamt))>; 1412} 1413 1414// PatFrag to allow ADDW/SUBW/MULW/SLLW to be selected from i64 add/sub/mul/shl 1415// if only the lower 32 bits of their result is used. 1416class binop_allwusers<SDPatternOperator operator> 1417 : PatFrag<(ops node:$lhs, node:$rhs), 1418 (operator node:$lhs, node:$rhs), [{ 1419 return hasAllWUsers(Node); 1420}]>; 1421 1422def sexti32_allwusers : PatFrag<(ops node:$src), 1423 (sext_inreg node:$src, i32), [{ 1424 return hasAllWUsers(Node); 1425}]>; 1426 1427let Predicates = [IsRV64] in { 1428 1429/// sext and zext 1430 1431// Sign extend is not needed if all users are W instructions. 1432def : Pat<(sexti32_allwusers GPR:$rs1), (XLenVT GPR:$rs1)>; 1433 1434def : Pat<(sext_inreg GPR:$rs1, i32), (ADDIW GPR:$rs1, 0)>; 1435 1436/// ALU operations 1437 1438def : Pat<(i64 (srl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)), 1439 (SRLIW GPR:$rs1, uimm5:$shamt)>; 1440def : Pat<(i64 (srl (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt)), 1441 (SRLIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>; 1442def : Pat<(sra (sext_inreg GPR:$rs1, i32), uimm5:$shamt), 1443 (SRAIW GPR:$rs1, uimm5:$shamt)>; 1444def : Pat<(i64 (sra (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt)), 1445 (SRAIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>; 1446 1447def : PatGprGpr<shiftopw<riscv_sllw>, SLLW>; 1448def : PatGprGpr<shiftopw<riscv_srlw>, SRLW>; 1449def : PatGprGpr<shiftopw<riscv_sraw>, SRAW>; 1450 1451// Select W instructions if only the lower 32 bits of the result are used. 1452def : PatGprGpr<binop_allwusers<add>, ADDW>; 1453def : PatGprSimm12<binop_allwusers<add>, ADDIW>; 1454def : PatGprGpr<binop_allwusers<sub>, SUBW>; 1455def : PatGprImm<binop_allwusers<shl>, SLLIW, uimm5>; 1456 1457// If this is a shr of a value sign extended from i32, and all the users only 1458// use the lower 32 bits, we can use an sraiw to remove the sext_inreg. This 1459// occurs because SimplifyDemandedBits prefers srl over sra. 1460def : Pat<(binop_allwusers<srl> (sext_inreg GPR:$rs1, i32), uimm5:$shamt), 1461 (SRAIW GPR:$rs1, uimm5:$shamt)>; 1462 1463/// Loads 1464 1465defm : LdPat<sextloadi32, LW, i64>; 1466defm : LdPat<extloadi32, LW, i64>; 1467defm : LdPat<zextloadi32, LWU, i64>; 1468defm : LdPat<load, LD, i64>; 1469 1470/// Stores 1471 1472defm : StPat<truncstorei32, SW, GPR, i64>; 1473defm : StPat<store, SD, GPR, i64>; 1474} // Predicates = [IsRV64] 1475 1476/// readcyclecounter 1477// On RV64, we can directly read the 64-bit "cycle" CSR. 1478let Predicates = [IsRV64] in 1479def : Pat<(i64 (readcyclecounter)), (CSRRS CYCLE.Encoding, X0)>; 1480// On RV32, ReadCycleWide will be expanded to the suggested loop reading both 1481// halves of the 64-bit "cycle" CSR. 1482let Predicates = [IsRV32], usesCustomInserter = 1, hasNoSchedulingInfo = 1 in 1483def ReadCycleWide : Pseudo<(outs GPR:$lo, GPR:$hi), (ins), 1484 [(set GPR:$lo, GPR:$hi, (riscv_read_cycle_wide))], 1485 "", "">; 1486 1487/// traps 1488 1489// We lower `trap` to `unimp`, as this causes a hard exception on nearly all 1490// systems. 1491def : Pat<(trap), (UNIMP)>; 1492 1493// We lower `debugtrap` to `ebreak`, as this will get the attention of the 1494// debugger if possible. 1495def : Pat<(debugtrap), (EBREAK)>; 1496 1497/// Simple optimization 1498def : Pat<(add GPR:$rs1, (AddiPair:$rs2)), 1499 (ADDI (ADDI GPR:$rs1, (AddiPairImmB AddiPair:$rs2)), 1500 (AddiPairImmA GPR:$rs2))>; 1501 1502let Predicates = [IsRV64] in { 1503// Select W instructions if only the lower 32-bits of the result are used. 1504def : Pat<(binop_allwusers<add> GPR:$rs1, (AddiPair:$rs2)), 1505 (ADDIW (ADDIW GPR:$rs1, (AddiPairImmB AddiPair:$rs2)), 1506 (AddiPairImmA AddiPair:$rs2))>; 1507} 1508 1509//===----------------------------------------------------------------------===// 1510// Standard extensions 1511//===----------------------------------------------------------------------===// 1512 1513include "RISCVInstrInfoM.td" 1514include "RISCVInstrInfoA.td" 1515include "RISCVInstrInfoF.td" 1516include "RISCVInstrInfoD.td" 1517include "RISCVInstrInfoC.td" 1518include "RISCVInstrInfoZb.td" 1519include "RISCVInstrInfoZk.td" 1520include "RISCVInstrInfoV.td" 1521include "RISCVInstrInfoZfh.td" 1522