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