2391 lines · plain
1//===-- RISCVInstrInfo.td - Target Description for RISC-V --*- tablegen -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//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 17class RVSDNode<string opcode, SDTypeProfile type_profile,18 list<SDNodeProperty> properties = []>19 : SDNode<"RISCVISD::" # opcode, type_profile, properties> {20 bit HasPassthruOp = false;21 bit HasMaskOp = false;22 let TSFlags{0} = HasPassthruOp;23 let TSFlags{1} = HasMaskOp;24}25 26// Target-independent type requirements, but with target-specific formats.27def SDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>,28 SDTCisVT<1, i32>]>;29def SDT_CallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>,30 SDTCisVT<1, i32>]>;31 32// Target-dependent type requirements.33def SDT_RISCVCall : SDTypeProfile<0, -1, [SDTCisVT<0, XLenVT>]>;34def SDT_RISCVSelectCC : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>,35 SDTCisVT<3, OtherVT>,36 SDTCisSameAs<0, 4>,37 SDTCisSameAs<4, 5>]>;38def SDT_RISCVBrCC : SDTypeProfile<0, 4, [SDTCisSameAs<0, 1>,39 SDTCisVT<2, OtherVT>,40 SDTCisVT<3, OtherVT>]>;41def SDT_RISCVIntUnaryOpW : SDTypeProfile<1, 1, [42 SDTCisSameAs<0, 1>, SDTCisVT<0, i64>43]>;44def SDT_RISCVIntBinOpW : SDTypeProfile<1, 2, [45 SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, 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 54def riscv_call : RVSDNode<"CALL", SDT_RISCVCall,55 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,56 SDNPVariadic]>;57def riscv_tail : RVSDNode<"TAIL", SDT_RISCVCall,58 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,59 SDNPVariadic]>;60 61// Software guarded calls for large code model62def riscv_sw_guarded_call : RVSDNode<"SW_GUARDED_CALL", SDT_RISCVCall,63 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,64 SDNPVariadic]>;65def riscv_sw_guarded_tail : RVSDNode<"SW_GUARDED_TAIL", SDT_RISCVCall,66 [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,67 SDNPVariadic]>;68 69def riscv_ret_glue : RVSDNode<"RET_GLUE", SDTNone,70 [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;71def riscv_sret_glue : RVSDNode<"SRET_GLUE", SDTNone,72 [SDNPHasChain, SDNPOptInGlue]>;73def riscv_mret_glue : RVSDNode<"MRET_GLUE", SDTNone,74 [SDNPHasChain, SDNPOptInGlue]>;75def riscv_mnret_glue : RVSDNode<"MNRET_GLUE", SDTNone,76 [SDNPHasChain, SDNPOptInGlue]>;77def riscv_mileaveret_glue : RVSDNode<"QC_C_MILEAVERET_GLUE", SDTNone,78 [SDNPHasChain, SDNPOptInGlue]>;79 80// Select with condition operator - This selects between a true value and81// a false value (ops #3 and #4) based on the boolean result of comparing82// the lhs and rhs (ops #0 and #1) of a conditional expression with the83// condition code in op #2, a XLenVT constant from the ISD::CondCode enum.84// The lhs and rhs are XLenVT integers. The true and false values can be85// integer or floating point.86def riscv_selectcc : RVSDNode<"SELECT_CC", SDT_RISCVSelectCC>;87def riscv_brcc : RVSDNode<"BR_CC", SDT_RISCVBrCC,88 [SDNPHasChain]>;89 90// Software guarded BRIND node. Operand is the target address.91def riscv_sw_guarded_brind : RVSDNode<"SW_GUARDED_BRIND",92 SDTBrind, [SDNPHasChain]>;93 94// RV64I shifts, directly matching the semantics of the named RISC-V95// instructions.96def riscv_sllw : RVSDNode<"SLLW", SDT_RISCVIntBinOpW>;97def riscv_sraw : RVSDNode<"SRAW", SDT_RISCVIntBinOpW>;98def riscv_srlw : RVSDNode<"SRLW", SDT_RISCVIntBinOpW>;99 100// Reads value of CSR. The first operand is the address of the required CSR.101// The result is the read value.102def riscv_read_csr : RVSDNode<"READ_CSR",103 SDTypeProfile<1, 1, [SDTCisInt<0>,104 SDTCisInt<1>]>,105 [SDNPHasChain]>;106// Write value to CSR. The first operand is the address of the required CSR,107// the second is the value to write.108def riscv_write_csr : RVSDNode<"WRITE_CSR",109 SDTypeProfile<0, 2, [SDTCisInt<0>,110 SDTCisInt<1>]>,111 [SDNPHasChain]>;112 113// Read and write value of CSR. The first operand is the address of the114// required CSR, the second is the value to write, and the result is the115// read value (before modification).116def riscv_swap_csr : RVSDNode<"SWAP_CSR",117 SDTypeProfile<1, 2, [SDTCisInt<0>,118 SDTCisInt<1>,119 SDTCisInt<2>]>,120 [SDNPHasChain]>;121 122// Clear bits of CSR. The first operand is the address of the required CSR,123// the second is the bitmask of cleared bits.124def riscv_clear_csr : RVSDNode<"CLEAR_CSR",125 SDTypeProfile<0, 2, [SDTCisInt<0>,126 SDTCisInt<1>]>,127 [SDNPHasChain]>;128 129// Set bits of CSR. The first operand is the address of the required CSR,130// the second is the bitmask of bits to set.131def riscv_set_csr : RVSDNode<"SET_CSR",132 SDTypeProfile<0, 2, [SDTCisInt<0>,133 SDTCisInt<1>]>,134 [SDNPHasChain]>;135 136// A read of the 64-bit counter CSR on a 32-bit target (returns (Lo, Hi)).137// It takes a chain operand and another two target constant operands (the138// CSR numbers of the low and high parts of the counter).139def riscv_read_counter_wide : RVSDNode<"READ_COUNTER_WIDE",140 SDTypeProfile<2, 2, [SDTCisVT<0, i32>,141 SDTCisVT<1, i32>,142 SDTCisInt<2>,143 SDTCisInt<3>]>,144 [SDNPHasChain, SDNPSideEffect]>;145 146// Add the Lo 12 bits from an address. Selected to ADDI.147def riscv_add_lo : RVSDNode<"ADD_LO", SDTIntBinOp>;148 149// Get the Hi 20 bits from an address. Selected to LUI.150def riscv_hi : RVSDNode<"HI", SDTIntUnaryOp>;151 152// Represents an AUIPC+ADDI pair. Selected to PseudoLLA.153def riscv_lla : RVSDNode<"LLA", SDTIntUnaryOp>;154 155// Selected as PseudoAddTPRel. Used to emit a TP-relative relocation.156def riscv_add_tprel : RVSDNode<"ADD_TPREL",157 SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>,158 SDTCisSameAs<0, 2>,159 SDTCisSameAs<0, 3>,160 SDTCisInt<0>]>>;161 162// To avoid stack clash, allocation is performed by block and each block is163// probed.164def riscv_probed_alloca : RVSDNode<"PROBED_ALLOCA",165 SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>,166 [SDNPHasChain, SDNPMayStore]>;167 168 169defvar GPRPairVT = untyped;170 171/// Turn a pair of `i<xlen>`s into an even-odd register pair (`untyped`).172/// - Output: `untyped` even-odd register pair173/// - Input 0: `i<xlen>` low-order bits, for even register.174/// - Input 1: `i<xlen>` high-order bits, for odd register.175def riscv_build_gpr_pair : RVSDNode<"BuildGPRPair",176 SDTypeProfile<1, 2, [SDTCisVT<0, GPRPairVT>,177 SDTCisVT<1, XLenVT>,178 SDTCisVT<2, XLenVT>]>>;179 180/// Turn an even-odd register pair (`untyped`) into a pair of `i<xlen>`s.181/// - Output 0: `i<xlen>` low-order bits, from even register.182/// - Output 1: `i<xlen>` high-order bits, from odd register.183/// - Input: `untyped` even-odd register pair184def riscv_split_gpr_pair : RVSDNode<"SplitGPRPair",185 SDTypeProfile<2, 1, [SDTCisVT<0, XLenVT>,186 SDTCisVT<1, XLenVT>,187 SDTCisVT<2, GPRPairVT>]>>;188 189//===----------------------------------------------------------------------===//190// Operand and SDNode transformation definitions.191//===----------------------------------------------------------------------===//192 193class ImmXLenAsmOperand<string prefix, string suffix = ""> : AsmOperandClass {194 let Name = prefix # "ImmXLen" # suffix;195 let RenderMethod = "addImmOperands";196 let DiagnosticType = !strconcat("Invalid", Name);197}198 199class ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass {200 let Name = prefix # "Imm" # width # suffix;201 let RenderMethod = "addImmOperands";202 let DiagnosticType = !strconcat("Invalid", Name);203}204 205def ImmZeroAsmOperand : AsmOperandClass {206 let Name = "ImmZero";207 let RenderMethod = "addImmOperands";208 let DiagnosticType = !strconcat("Invalid", Name);209 let DiagnosticString = "immediate must be zero";210}211 212// A parse method for (${gpr}) or 0(${gpr}), where the 0 is be silently ignored.213def ZeroOffsetMemOpOperand : AsmOperandClass {214 let Name = "ZeroOffsetMemOpOperand";215 let RenderMethod = "addRegOperands";216 let PredicateMethod = "isGPR";217 let ParserMethod = "parseZeroOffsetMemOp";218}219 220class MemOperand<RegisterClass regClass> : RegisterOperand<regClass>{221 let OperandType = "OPERAND_MEMORY";222}223 224def GPRMemZeroOffset : MemOperand<GPR> {225 let ParserMatchClass = ZeroOffsetMemOpOperand;226 let PrintMethod = "printZeroOffsetMemOp";227}228 229def GPRMem : MemOperand<GPR>;230 231def SPMem : MemOperand<SP>;232 233def GPRCMem : MemOperand<GPRC>;234 235class SImmAsmOperand<int width, string suffix = "">236 : ImmAsmOperand<"S", width, suffix> {237}238 239class UImmAsmOperand<int width, string suffix = "">240 : ImmAsmOperand<"U", width, suffix> {241}242 243class BareSImmNLsb0AsmOperand<int width>244 : ImmAsmOperand<"BareS", width, "Lsb0"> {245 let PredicateMethod = "isBareSimmNLsb0<" # width # ">";246}247 248class RISCVOp<ValueType vt = XLenVT> : Operand<vt> {249 let OperandNamespace = "RISCVOp";250}251 252class RISCVUImmOp<int bitsNum> : RISCVOp {253 let ParserMatchClass = UImmAsmOperand<bitsNum>;254 let EncoderMethod = "getImmOpValue";255 let DecoderMethod = "decodeUImmOperand<" # bitsNum # ">";256 let OperandType = "OPERAND_UIMM" # bitsNum;257 let MCOperandPredicate = [{258 int64_t Imm;259 if (!MCOp.evaluateAsConstantImm(Imm))260 return false;261 return isUInt<}]# bitsNum #[{>(Imm);262 }];263}264 265class RISCVUImmLeafOp<int bitsNum> :266 RISCVUImmOp<bitsNum>, ImmLeaf<XLenVT, "return isUInt<" # bitsNum # ">(Imm);">;267 268class RISCVSImmOp<int bitsNum> : RISCVOp {269 let ParserMatchClass = SImmAsmOperand<bitsNum>;270 let EncoderMethod = "getImmOpValue";271 let DecoderMethod = "decodeSImmOperand<" # bitsNum # ">";272 let OperandType = "OPERAND_SIMM" # bitsNum;273 let MCOperandPredicate = [{274 int64_t Imm;275 if (!MCOp.evaluateAsConstantImm(Imm))276 return false;277 return isInt<}] # bitsNum # [{>(Imm);278 }];279}280 281class RISCVSImmLeafOp<int bitsNum> :282 RISCVSImmOp<bitsNum>, ImmLeaf<XLenVT, "return isInt<" # bitsNum # ">(Imm);">;283 284def FenceArg : AsmOperandClass {285 let Name = "FenceArg";286 let RenderMethod = "addFenceArgOperands";287 let ParserMethod = "parseFenceArg";288}289 290def fencearg : RISCVOp {291 let ParserMatchClass = FenceArg;292 let PrintMethod = "printFenceArg";293 let DecoderMethod = "decodeUImmOperand<4>";294 let OperandType = "OPERAND_UIMM4";295}296 297def UImmLog2XLenAsmOperand : AsmOperandClass {298 let Name = "UImmLog2XLen";299 let RenderMethod = "addImmOperands";300 let DiagnosticType = "InvalidUImmLog2XLen";301}302 303def uimmlog2xlen : RISCVOp, ImmLeaf<XLenVT, [{304 if (Subtarget->is64Bit())305 return isUInt<6>(Imm);306 return isUInt<5>(Imm);307}]> {308 let ParserMatchClass = UImmLog2XLenAsmOperand;309 let DecoderMethod = "decodeUImmLog2XLenOperand";310 let MCOperandPredicate = [{311 int64_t Imm;312 if (!MCOp.evaluateAsConstantImm(Imm))313 return false;314 if (STI.getTargetTriple().isArch64Bit())315 return isUInt<6>(Imm);316 return isUInt<5>(Imm);317 }];318 let OperandType = "OPERAND_UIMMLOG2XLEN";319}320 321def InsnDirectiveOpcode : AsmOperandClass {322 let Name = "InsnDirectiveOpcode";323 let ParserMethod = "parseInsnDirectiveOpcode";324 let RenderMethod = "addImmOperands";325 let PredicateMethod = "isImm";326}327 328def uimm1 : RISCVUImmLeafOp<1>;329def uimm2 : RISCVUImmLeafOp<2>;330def uimm3 : RISCVUImmLeafOp<3>;331def uimm4 : RISCVUImmLeafOp<4>;332def uimm5 : RISCVUImmLeafOp<5>;333def uimm6 : RISCVUImmLeafOp<6>;334def uimm7_opcode : RISCVUImmOp<7> {335 let ParserMatchClass = InsnDirectiveOpcode;336}337def uimm7 : RISCVUImmLeafOp<7>;338def uimm8 : RISCVUImmOp<8>;339def uimm16 : RISCVUImmOp<16>;340def uimm32 : RISCVUImmOp<32>;341def uimm48 : RISCVUImmOp<48>;342def uimm64 : RISCVUImmOp<64>;343 344def simm12_lo : RISCVSImmLeafOp<12> {345 let ParserMatchClass = SImmAsmOperand<12, "LO">;346 let MCOperandPredicate = [{347 int64_t Imm;348 if (MCOp.evaluateAsConstantImm(Imm))349 return isInt<12>(Imm);350 return MCOp.isBareSymbolRef();351 }];352}353 354// A 12-bit signed immediate which cannot fit in 6-bit signed immediate,355// but even negative value fit in 12-bit.356def simm12_no6 : ImmLeaf<XLenVT, [{357 return isInt<12>(Imm) && !isInt<6>(Imm) && isInt<12>(-Imm);}]>;358 359class BareSImm13Lsb0MaybeSym : Operand<OtherVT> {360 let MCOperandPredicate = [{361 int64_t Imm;362 if (MCOp.evaluateAsConstantImm(Imm))363 return isShiftedInt<12, 1>(Imm);364 return MCOp.isBareSymbolRef();365 }];366}367 368// A 13-bit signed immediate where the least significant bit is zero. The ImmLeaf369// is needed so that the CompressInstEmitter can correctly add checks for the370// compress patterns that involve instructions that use this operand. Similar to371// bare_simm9_lsb0 in RISCVInstrInfoC.td.372def bare_simm13_lsb0 : BareSImm13Lsb0MaybeSym,373 ImmLeaf<XLenVT, [{return isShiftedInt<12, 1>(Imm);}]> {374 let ParserMatchClass = BareSImmNLsb0AsmOperand<13>;375 let PrintMethod = "printBranchOperand";376 let EncoderMethod = "getImmOpValueAsrN<1>";377 let DecoderMethod = "decodeSImmOperandAndLslN<13, 1>";378 let OperandType = "OPERAND_PCREL";379}380 381// We need this (sort of) duplicate definition since adding ImmLeaf to382// bare_simm13_lsb0 above makes it not sit well with codegen patterns where it383// is used to match with a basic block (eg. BccPat<>).384def bare_simm13_lsb0_bb : BareSImm13Lsb0MaybeSym;385 386class UImm20OperandMaybeSym : RISCVUImmOp<20> {387 let MCOperandPredicate = [{388 int64_t Imm;389 if (MCOp.evaluateAsConstantImm(Imm))390 return isUInt<20>(Imm);391 return MCOp.isBareSymbolRef();392 }];393}394 395def uimm20_lui : UImm20OperandMaybeSym {396 let ParserMatchClass = UImmAsmOperand<20, "LUI">;397}398def uimm20_auipc : UImm20OperandMaybeSym {399 let ParserMatchClass = UImmAsmOperand<20, "AUIPC">;400}401 402def uimm20 : RISCVUImmOp<20>;403 404def Simm21Lsb0JALAsmOperand : BareSImmNLsb0AsmOperand<21> {405 let ParserMethod = "parseJALOffset";406}407 408// A 21-bit signed immediate where the least significant bit is zero.409def simm21_lsb0_jal : Operand<OtherVT>,410 ImmLeaf<XLenVT, [{return isShiftedInt<20, 1>(Imm);}]> {411 let ParserMatchClass = Simm21Lsb0JALAsmOperand;412 let PrintMethod = "printBranchOperand";413 let EncoderMethod = "getImmOpValueAsrN<1>";414 let DecoderMethod = "decodeSImmOperandAndLslN<21, 1>";415 let MCOperandPredicate = [{416 int64_t Imm;417 if (MCOp.evaluateAsConstantImm(Imm))418 return isShiftedInt<20, 1>(Imm);419 return MCOp.isBareSymbolRef();420 }];421 let OperandType = "OPERAND_PCREL";422}423 424def BareSymbol : AsmOperandClass {425 let Name = "BareSymbol";426 let RenderMethod = "addImmOperands";427 let DiagnosticType = "InvalidBareSymbol";428 let DiagnosticString = "operand must be a bare symbol name";429 let ParserMethod = "parseBareSymbol";430}431 432// A bare symbol.433def bare_symbol : Operand<XLenVT> {434 let ParserMatchClass = BareSymbol;435}436 437def CallSymbol : AsmOperandClass {438 let Name = "CallSymbol";439 let RenderMethod = "addImmOperands";440 let DiagnosticType = "InvalidCallSymbol";441 let DiagnosticString = "operand must be a bare symbol name";442 let ParserMethod = "parseCallSymbol";443}444 445// A bare symbol used in call/tail only.446def call_symbol : Operand<XLenVT> {447 let ParserMatchClass = CallSymbol;448}449 450def PseudoJumpSymbol : AsmOperandClass {451 let Name = "PseudoJumpSymbol";452 let RenderMethod = "addImmOperands";453 let DiagnosticType = "InvalidPseudoJumpSymbol";454 let DiagnosticString = "operand must be a valid jump target";455 let ParserMethod = "parsePseudoJumpSymbol";456}457 458// A bare symbol used for pseudo jumps only.459def pseudo_jump_symbol : Operand<XLenVT> {460 let ParserMatchClass = PseudoJumpSymbol;461}462 463def TPRelAddSymbol : AsmOperandClass {464 let Name = "TPRelAddSymbol";465 let RenderMethod = "addImmOperands";466 let DiagnosticType = "InvalidTPRelAddSymbol";467 let DiagnosticString = "operand must be a symbol with %tprel_add specifier";468 let ParserMethod = "parseOperandWithSpecifier";469}470 471// A bare symbol with the %tprel_add variant.472def tprel_add_symbol : Operand<XLenVT> {473 let ParserMatchClass = TPRelAddSymbol;474}475 476def CSRSystemRegister : AsmOperandClass {477 let Name = "CSRSystemRegister";478 let ParserMethod = "parseCSRSystemRegister";479 let DiagnosticType = "InvalidCSRSystemRegister";480}481 482def csr_sysreg : RISCVOp, TImmLeaf<XLenVT, "return isUInt<12>(Imm);"> {483 let ParserMatchClass = CSRSystemRegister;484 let PrintMethod = "printCSRSystemRegister";485 let DecoderMethod = "decodeUImmOperand<12>";486 let OperandType = "OPERAND_UIMM12";487}488 489// A parameterized register class alternative to i32imm/i64imm from Target.td.490def ixlenimm : Operand<XLenVT>;491 492// Condition code used by select and short forward branch pseudos.493def cond_code : RISCVOp {494 let OperandType = "OPERAND_COND_CODE";495}496 497def ixlenimm_li : Operand<XLenVT> {498 let ParserMatchClass = ImmXLenAsmOperand<"", "LI">;499}500 501// Accepts subset of LI operands, used by LAImm and LLAImm502def ixlenimm_li_restricted : Operand<XLenVT> {503 let ParserMatchClass = ImmXLenAsmOperand<"", "LI_Restricted">;504}505 506// Standalone (codegen-only) immleaf patterns.507 508// A 12-bit signed immediate plus one where the imm range will be -2047~2048.509def simm12_plus1 : ImmLeaf<XLenVT,510 [{return (isInt<12>(Imm) && Imm != -2048) || Imm == 2048;}]>;511 512// A 6-bit constant greater than 32.513def uimm6gt32 : ImmLeaf<XLenVT, [{514 return isUInt<6>(Imm) && Imm > 32;515}]>;516 517// Addressing modes.518def AddrRegImm : ComplexPattern<iPTR, 2, "SelectAddrRegImm">;519 520class AddrRegRegScale<int N>521 : ComplexPattern<iPTR, 3, "SelectAddrRegRegScale<"#N#">">;522class AddrRegZextRegScale<int N>523 : ComplexPattern<i64, 3, "SelectAddrRegZextRegScale<"#N#", 32>",524 [], [], 10>;525 526// Return the negation of an immediate value.527def NegImm : SDNodeXForm<imm, [{528 return CurDAG->getSignedTargetConstant(-N->getSExtValue(), SDLoc(N),529 N->getValueType(0));530}]>;531def GINegImm : GICustomOperandRenderer<"renderNegImm">,532 GISDNodeXFormEquiv<NegImm>;533 534// Return an immediate value minus 32.535def ImmSub32 : SDNodeXForm<imm, [{536 return CurDAG->getSignedTargetConstant(N->getSExtValue() - 32, SDLoc(N),537 N->getValueType(0));538}]>;539 540// Return an immediate subtracted from XLen.541def ImmSubFromXLen : SDNodeXForm<imm, [{542 uint64_t XLen = Subtarget->getXLen();543 return CurDAG->getTargetConstant(XLen - N->getZExtValue(), SDLoc(N),544 N->getValueType(0));545}]>;546def GIImmSubFromXLen : GICustomOperandRenderer<"renderImmSubFromXLen">,547 GISDNodeXFormEquiv<ImmSubFromXLen>;548 549// Return an immediate subtracted from 32.550def ImmSubFrom32 : SDNodeXForm<imm, [{551 return CurDAG->getTargetConstant(32 - N->getZExtValue(), SDLoc(N),552 N->getValueType(0));553}]>;554def GIImmSubFrom32 : GICustomOperandRenderer<"renderImmSubFrom32">,555 GISDNodeXFormEquiv<ImmSubFrom32>;556 557// Check if (add r, imm) can be optimized to (ADDI (ADDI r, imm0), imm1),558// in which imm = imm0 + imm1 and both imm0 and imm1 are simm12. We make imm0559// as large as possible and imm1 as small as possible so that we might be able560// to use c.addi for the small immediate.561def AddiPair : ImmLeaf<XLenVT, [{562 // The immediate operand must be in range [-4096,-2049] or [2048,4094].563 return (-4096 <= Imm && Imm <= -2049) || (2048 <= Imm && Imm <= 4094);564}]>;565 566// Return imm - (imm < 0 ? -2048 : 2047).567def AddiPairImmSmall : SDNodeXForm<imm, [{568 int64_t Imm = N->getSExtValue();569 int64_t Adj = N->getSExtValue() < 0 ? -2048 : 2047;570 return CurDAG->getSignedTargetConstant(Imm - Adj, SDLoc(N),571 N->getValueType(0));572}]>;573def GIAddiPairImmSmall : GICustomOperandRenderer<"renderAddiPairImmSmall">,574 GISDNodeXFormEquiv<AddiPairImmSmall>;575 576// Return -2048 if immediate is negative or 2047 if positive. These are the577// largest simm12 values.578def AddiPairImmLarge : SDNodeXForm<imm, [{579 int64_t Imm = N->getSExtValue() < 0 ? -2048 : 2047;580 return CurDAG->getSignedTargetConstant(Imm, SDLoc(N), N->getValueType(0));581}]>;582def GIAddiPairImmLarge : GICustomOperandRenderer<"renderAddiPairImmLarge">,583 GISDNodeXFormEquiv<AddiPairImmLarge>;584 585def TrailingZeros : SDNodeXForm<imm, [{586 return CurDAG->getTargetConstant(llvm::countr_zero(N->getZExtValue()),587 SDLoc(N), N->getValueType(0));588}]>;589def GITrailingZeros : GICustomOperandRenderer<"renderTrailingZeros">,590 GISDNodeXFormEquiv<TrailingZeros>;591 592def XLenSubTrailingOnes : SDNodeXForm<imm, [{593 uint64_t XLen = Subtarget->getXLen();594 uint64_t TrailingOnes = llvm::countr_one(N->getZExtValue());595 return CurDAG->getTargetConstant(XLen - TrailingOnes, SDLoc(N),596 N->getValueType(0));597}]>;598def GIXLenSubTrailingOnes : GICustomOperandRenderer<"renderXLenSubTrailingOnes">,599 GISDNodeXFormEquiv<XLenSubTrailingOnes>;600 601// Checks if this mask is a non-empty sequence of ones starting at the602// most/least significant bit with the remainder zero and exceeds simm32/simm12.603def LeadingOnesMask : ImmLeaf<XLenVT, [{604 return !isInt<32>(Imm) && isMask_64(~Imm);605}], TrailingZeros>;606 607def TrailingOnesMask : IntImmLeaf<XLenVT, [{608 return !isInt<12>(Imm.getSExtValue()) && isMask_64(Imm.getZExtValue());609}], XLenSubTrailingOnes>;610 611// Similar to LeadingOnesMask, but only consider leading ones in the lower 32612// bits.613def LeadingOnesWMask : ImmLeaf<XLenVT, [{614 // If the value is a uint32 but not an int32, it must have bit 31 set and615 // bits 63:32 cleared. After that we're looking for a shifted mask but not616 // an all ones mask.617 return !isInt<32>(Imm) && isUInt<32>(Imm) && isShiftedMask_64(Imm) &&618 Imm != UINT64_C(0xffffffff);619}], TrailingZeros>;620 621//===----------------------------------------------------------------------===//622// Instruction Formats623//===----------------------------------------------------------------------===//624 625include "RISCVInstrFormats.td"626include "RISCVInstrFormatsC.td"627include "RISCVInstrFormatsV.td"628 629//===----------------------------------------------------------------------===//630// Instruction Class Templates631//===----------------------------------------------------------------------===//632 633class BranchCC_rri<bits<3> funct3, string opcodestr>634 : RVInstB<funct3, OPC_BRANCH, (outs),635 (ins GPR:$rs1, GPR:$rs2, bare_simm13_lsb0:$imm12),636 opcodestr, "$rs1, $rs2, $imm12">,637 Sched<[WriteJmp, ReadJmp, ReadJmp]> {638 let isBranch = 1;639 let isTerminator = 1;640 let hasSideEffects = 0;641 let mayLoad = 0;642 let mayStore = 0;643}644 645let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {646class Load_ri<bits<3> funct3, string opcodestr, DAGOperand rty = GPR>647 : RVInstI<funct3, OPC_LOAD, (outs rty:$rd), (ins GPRMem:$rs1, simm12_lo:$imm12),648 opcodestr, "$rd, ${imm12}(${rs1})">;649 650class HLoad_r<bits<7> funct7, bits<5> funct5, string opcodestr>651 : RVInstR<funct7, 0b100, OPC_SYSTEM, (outs GPR:$rd),652 (ins GPRMemZeroOffset:$rs1), opcodestr, "$rd, $rs1"> {653 let rs2 = funct5;654}655}656 657// Operands for stores are in the order srcreg, base, offset rather than658// reflecting the order these fields are specified in the instruction659// encoding.660let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {661class Store_rri<bits<3> funct3, string opcodestr, DAGOperand rty = GPR>662 : RVInstS<funct3, OPC_STORE, (outs),663 (ins rty:$rs2, GPRMem:$rs1, simm12_lo:$imm12),664 opcodestr, "$rs2, ${imm12}(${rs1})">;665 666class HStore_rr<bits<7> funct7, string opcodestr>667 : RVInstR<funct7, 0b100, OPC_SYSTEM, (outs),668 (ins GPR:$rs2, GPRMemZeroOffset:$rs1),669 opcodestr, "$rs2, $rs1"> {670 let rd = 0;671}672}673 674let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in675class ALU_ri<bits<3> funct3, string opcodestr>676 : RVInstI<funct3, OPC_OP_IMM, (outs GPR:$rd), (ins GPR:$rs1, simm12_lo:$imm12),677 opcodestr, "$rd, $rs1, $imm12">,678 Sched<[WriteIALU, ReadIALU]>;679 680let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in681class Shift_ri<bits<5> imm11_7, bits<3> funct3, string opcodestr>682 : RVInstIShift<imm11_7, funct3, OPC_OP_IMM, (outs GPR:$rd),683 (ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr,684 "$rd, $rs1, $shamt">;685 686let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in687class ALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr,688 bit Commutable = 0>689 : RVInstR<funct7, funct3, OPC_OP, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2),690 opcodestr, "$rd, $rs1, $rs2"> {691 let isCommutable = Commutable;692}693 694let hasNoSchedulingInfo = 1,695 hasSideEffects = 1, mayLoad = 0, mayStore = 0 in696class CSR_ir<bits<3> funct3, string opcodestr>697 : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), (ins csr_sysreg:$imm12, GPR:$rs1),698 opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR, ReadCSR]>;699 700let hasNoSchedulingInfo = 1,701 hasSideEffects = 1, mayLoad = 0, mayStore = 0 in702class CSR_ii<bits<3> funct3, string opcodestr>703 : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd),704 (ins csr_sysreg:$imm12, uimm5:$rs1),705 opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR]>;706 707let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in708class ShiftW_ri<bits<7> imm11_5, bits<3> funct3, string opcodestr>709 : RVInstIShiftW<imm11_5, funct3, OPC_OP_IMM_32, (outs GPR:$rd),710 (ins GPR:$rs1, uimm5:$shamt), opcodestr,711 "$rd, $rs1, $shamt">;712 713let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in714class ALUW_rr<bits<7> funct7, bits<3> funct3, string opcodestr,715 bit Commutable = 0>716 : RVInstR<funct7, funct3, OPC_OP_32, (outs GPR:$rd),717 (ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2"> {718 let isCommutable = Commutable;719}720 721let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in722class Priv<string opcodestr, bits<7> funct7>723 : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins), opcodestr, "">;724 725let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in726class Priv_rr<string opcodestr, bits<7> funct7>727 : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2),728 opcodestr, "$rs1, $rs2"> {729 let rd = 0;730}731 732let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in733class Unary_r<bits<12> imm12, bits<3> funct3, string opcodestr>734 : RVInstIUnary<imm12, funct3, OPC_OP_IMM, (outs GPR:$rd), (ins GPR:$rs1),735 opcodestr, "$rd, $rs1">;736 737let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in738class UnaryW_r<bits<12> imm12, bits<3> funct3, string opcodestr>739 : RVInstIUnary<imm12, funct3, OPC_OP_IMM_32, (outs GPR:$rd), (ins GPR:$rs1),740 opcodestr, "$rd, $rs1">;741 742//===----------------------------------------------------------------------===//743// Instructions744//===----------------------------------------------------------------------===//745 746let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {747let isReMaterializable = 1, isAsCheapAsAMove = 1,748 IsSignExtendingOpW = 1 in749def LUI : RVInstU<OPC_LUI, (outs GPR:$rd), (ins uimm20_lui:$imm20),750 "lui", "$rd, $imm20">, Sched<[WriteIALU]>;751 752def AUIPC : RVInstU<OPC_AUIPC, (outs GPR:$rd), (ins uimm20_auipc:$imm20),753 "auipc", "$rd, $imm20">, Sched<[WriteIALU]>;754 755def JAL : RVInstJ<OPC_JAL, (outs GPR:$rd), (ins simm21_lsb0_jal:$imm20),756 "jal", "$rd, $imm20">, Sched<[WriteJal]>;757 758def JALR : RVInstI<0b000, OPC_JALR, (outs GPR:$rd),759 (ins GPR:$rs1, simm12_lo:$imm12),760 "jalr", "$rd, ${imm12}(${rs1})">,761 Sched<[WriteJalr, ReadJalr]>;762} // hasSideEffects = 0, mayLoad = 0, mayStore = 0763 764def BEQ : BranchCC_rri<0b000, "beq">;765def BNE : BranchCC_rri<0b001, "bne">;766def BLT : BranchCC_rri<0b100, "blt">;767def BGE : BranchCC_rri<0b101, "bge">;768def BLTU : BranchCC_rri<0b110, "bltu">;769def BGEU : BranchCC_rri<0b111, "bgeu">;770 771let IsSignExtendingOpW = 1, canFoldAsLoad = 1, isReMaterializable = 1 in {772def LB : Load_ri<0b000, "lb">, Sched<[WriteLDB, ReadMemBase]>;773def LH : Load_ri<0b001, "lh">, Sched<[WriteLDH, ReadMemBase]>;774def LW : Load_ri<0b010, "lw">, Sched<[WriteLDW, ReadMemBase]>;775def LBU : Load_ri<0b100, "lbu">, Sched<[WriteLDB, ReadMemBase]>;776def LHU : Load_ri<0b101, "lhu">, Sched<[WriteLDH, ReadMemBase]>;777}778 779def SB : Store_rri<0b000, "sb">, Sched<[WriteSTB, ReadStoreData, ReadMemBase]>;780def SH : Store_rri<0b001, "sh">, Sched<[WriteSTH, ReadStoreData, ReadMemBase]>;781def SW : Store_rri<0b010, "sw">, Sched<[WriteSTW, ReadStoreData, ReadMemBase]>;782 783// ADDI isn't always rematerializable, but isReMaterializable will be used as784// a hint which is verified in isReMaterializableImpl.785let isReMaterializable = 1, isAsCheapAsAMove = 1 in786def ADDI : ALU_ri<0b000, "addi">;787 788let IsSignExtendingOpW = 1 in {789def SLTI : ALU_ri<0b010, "slti">;790def SLTIU : ALU_ri<0b011, "sltiu">;791}792 793let isReMaterializable = 1, isAsCheapAsAMove = 1 in {794def XORI : ALU_ri<0b100, "xori">;795def ORI : ALU_ri<0b110, "ori">;796}797 798def ANDI : ALU_ri<0b111, "andi">;799 800def SLLI : Shift_ri<0b00000, 0b001, "slli">,801 Sched<[WriteShiftImm, ReadShiftImm]>;802def SRLI : Shift_ri<0b00000, 0b101, "srli">,803 Sched<[WriteShiftImm, ReadShiftImm]>;804def SRAI : Shift_ri<0b01000, 0b101, "srai">,805 Sched<[WriteShiftImm, ReadShiftImm]>;806 807def ADD : ALU_rr<0b0000000, 0b000, "add", Commutable=1>,808 Sched<[WriteIALU, ReadIALU, ReadIALU]>;809def SUB : ALU_rr<0b0100000, 0b000, "sub">,810 Sched<[WriteIALU, ReadIALU, ReadIALU]>;811def SLL : ALU_rr<0b0000000, 0b001, "sll">,812 Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>;813let IsSignExtendingOpW = 1 in {814def SLT : ALU_rr<0b0000000, 0b010, "slt">,815 Sched<[WriteIALU, ReadIALU, ReadIALU]>;816def SLTU : ALU_rr<0b0000000, 0b011, "sltu">,817 Sched<[WriteIALU, ReadIALU, ReadIALU]>;818}819def XOR : ALU_rr<0b0000000, 0b100, "xor", Commutable=1>,820 Sched<[WriteIALU, ReadIALU, ReadIALU]>;821def SRL : ALU_rr<0b0000000, 0b101, "srl">,822 Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>;823def SRA : ALU_rr<0b0100000, 0b101, "sra">,824 Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>;825def OR : ALU_rr<0b0000000, 0b110, "or", Commutable=1>,826 Sched<[WriteIALU, ReadIALU, ReadIALU]>;827def AND : ALU_rr<0b0000000, 0b111, "and", Commutable=1>,828 Sched<[WriteIALU, ReadIALU, ReadIALU]>;829 830let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in {831def FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs),832 (ins fencearg:$pred, fencearg:$succ),833 "fence", "$pred, $succ">, Sched<[]> {834 bits<4> pred;835 bits<4> succ;836 837 let rs1 = 0;838 let rd = 0;839 let imm12 = {0b0000,pred,succ};840}841 842def FENCE_TSO : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins), "fence.tso", "">, Sched<[]> {843 let rs1 = 0;844 let rd = 0;845 let imm12 = {0b1000,0b0011,0b0011};846}847 848def FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), "fence.i", "">, Sched<[]> {849 let rs1 = 0;850 let rd = 0;851 let imm12 = 0;852}853 854def ECALL : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ecall", "">, Sched<[WriteJmp]> {855 let rs1 = 0;856 let rd = 0;857 let imm12 = 0;858}859 860let isTrap = 1 in861def EBREAK : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ebreak", "">,862 Sched<[]> {863 let rs1 = 0;864 let rd = 0;865 let imm12 = 1;866}867 868// This is a de facto standard (as set by GNU binutils) 32-bit unimplemented869// instruction (i.e., it should always trap, if your implementation has invalid870// instruction traps).871let isTrap = 1 in872def UNIMP : RVInstI<0b001, OPC_SYSTEM, (outs), (ins), "unimp", "">,873 Sched<[]> {874 let rs1 = 0;875 let rd = 0;876 let imm12 = 0b110000000000;877}878 879} // hasSideEffects = 1, mayLoad = 0, mayStore = 0880 881def CSRRW : CSR_ir<0b001, "csrrw">;882def CSRRS : CSR_ir<0b010, "csrrs">;883def CSRRC : CSR_ir<0b011, "csrrc">;884 885def CSRRWI : CSR_ii<0b101, "csrrwi">;886def CSRRSI : CSR_ii<0b110, "csrrsi">;887def CSRRCI : CSR_ii<0b111, "csrrci">;888 889/// RV64I instructions890 891let Predicates = [IsRV64] in {892let canFoldAsLoad = 1, isReMaterializable = 1 in {893def LWU : Load_ri<0b110, "lwu">, Sched<[WriteLDW, ReadMemBase]>;894def LD : Load_ri<0b011, "ld">, Sched<[WriteLDD, ReadMemBase]>;895}896def SD : Store_rri<0b011, "sd">, Sched<[WriteSTD, ReadStoreData, ReadMemBase]>;897 898let IsSignExtendingOpW = 1 in {899let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in900def ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd),901 (ins GPR:$rs1, simm12_lo:$imm12),902 "addiw", "$rd, $rs1, $imm12">,903 Sched<[WriteIALU32, ReadIALU32]>;904 905def SLLIW : ShiftW_ri<0b0000000, 0b001, "slliw">,906 Sched<[WriteShiftImm32, ReadShiftImm32]>;907def SRLIW : ShiftW_ri<0b0000000, 0b101, "srliw">,908 Sched<[WriteShiftImm32, ReadShiftImm32]>;909def SRAIW : ShiftW_ri<0b0100000, 0b101, "sraiw">,910 Sched<[WriteShiftImm32, ReadShiftImm32]>;911 912def ADDW : ALUW_rr<0b0000000, 0b000, "addw", Commutable=1>,913 Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;914def SUBW : ALUW_rr<0b0100000, 0b000, "subw">,915 Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;916def SLLW : ALUW_rr<0b0000000, 0b001, "sllw">,917 Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>;918def SRLW : ALUW_rr<0b0000000, 0b101, "srlw">,919 Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>;920def SRAW : ALUW_rr<0b0100000, 0b101, "sraw">,921 Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>;922} // IsSignExtendingOpW = 1923} // Predicates = [IsRV64]924 925//===----------------------------------------------------------------------===//926// Privileged instructions927//===----------------------------------------------------------------------===//928 929let isBarrier = 1, isReturn = 1, isTerminator = 1 in {930def SRET : Priv<"sret", 0b0001000>, Sched<[]> {931 let rd = 0;932 let rs1 = 0;933 let rs2 = 0b00010;934}935 936def MRET : Priv<"mret", 0b0011000>, Sched<[]> {937 let rd = 0;938 let rs1 = 0;939 let rs2 = 0b00010;940}941 942let Predicates = [HasStdExtSmrnmi] in {943def MNRET : Priv<"mnret", 0b0111000>, Sched<[]> {944 let rd = 0;945 let rs1 = 0;946 let rs2 = 0b00010;947}948}// Predicates = [HasStdExtSmrnmi]949} // isBarrier = 1, isReturn = 1, isTerminator = 1950 951 952def WFI : Priv<"wfi", 0b0001000>, Sched<[]> {953 let rd = 0;954 let rs1 = 0;955 let rs2 = 0b00101;956}957 958let Predicates = [HasStdExtSvinval] in {959def SFENCE_W_INVAL : Priv<"sfence.w.inval", 0b0001100>, Sched<[]> {960 let rd = 0;961 let rs1 = 0;962 let rs2 = 0;963}964 965def SFENCE_INVAL_IR : Priv<"sfence.inval.ir", 0b0001100>, Sched<[]> {966 let rd = 0;967 let rs1 = 0;968 let rs2 = 0b00001;969}970def SINVAL_VMA : Priv_rr<"sinval.vma", 0b0001011>, Sched<[]>;971def HINVAL_VVMA : Priv_rr<"hinval.vvma", 0b0010011>, Sched<[]>;972def HINVAL_GVMA : Priv_rr<"hinval.gvma", 0b0110011>, Sched<[]>;973} // Predicates = [HasStdExtSvinval]974 975def SFENCE_VMA : Priv_rr<"sfence.vma", 0b0001001>, Sched<[]>;976 977let Predicates = [HasStdExtH] in {978def HFENCE_VVMA : Priv_rr<"hfence.vvma", 0b0010001>, Sched<[]>;979def HFENCE_GVMA : Priv_rr<"hfence.gvma", 0b0110001>, Sched<[]>;980 981def HLV_B : HLoad_r<0b0110000, 0b00000, "hlv.b">, Sched<[]>;982def HLV_BU : HLoad_r<0b0110000, 0b00001, "hlv.bu">, Sched<[]>;983def HLV_H : HLoad_r<0b0110010, 0b00000, "hlv.h">, Sched<[]>;984def HLV_HU : HLoad_r<0b0110010, 0b00001, "hlv.hu">, Sched<[]>;985def HLVX_HU : HLoad_r<0b0110010, 0b00011, "hlvx.hu">, Sched<[]>;986def HLV_W : HLoad_r<0b0110100, 0b00000, "hlv.w">, Sched<[]>;987def HLVX_WU : HLoad_r<0b0110100, 0b00011, "hlvx.wu">, Sched<[]>;988def HSV_B : HStore_rr<0b0110001, "hsv.b">, Sched<[]>;989def HSV_H : HStore_rr<0b0110011, "hsv.h">, Sched<[]>;990def HSV_W : HStore_rr<0b0110101, "hsv.w">, Sched<[]>;991}992let Predicates = [IsRV64, HasStdExtH] in {993def HLV_WU : HLoad_r<0b0110100, 0b00001, "hlv.wu">, Sched<[]>;994def HLV_D : HLoad_r<0b0110110, 0b00000, "hlv.d">, Sched<[]>;995def HSV_D : HStore_rr<0b0110111, "hsv.d">, Sched<[]>;996}997 998let Predicates = [HasStdExtSmctrOrSsctr] in {999def SCTRCLR : Priv<"sctrclr", 0b0001000>, Sched<[]> {1000 let rd = 0;1001 let rs1 = 0;1002 let rs2 = 0b00100;1003}1004}1005 1006//===----------------------------------------------------------------------===//1007// Debug instructions1008//===----------------------------------------------------------------------===//1009 1010let isBarrier = 1, isReturn = 1, isTerminator = 1 in {1011def DRET : Priv<"dret", 0b0111101>, Sched<[]> {1012 let rd = 0;1013 let rs1 = 0;1014 let rs2 = 0b10010;1015}1016} // isBarrier = 1, isReturn = 1, isTerminator = 11017 1018//===----------------------------------------------------------------------===//1019// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)1020//===----------------------------------------------------------------------===//1021 1022// Note that the size is 32 because up to 8 32-bit instructions are needed to1023// generate an arbitrary 64-bit immediate. However, the size does not really1024// matter since PseudoLI is currently only used in the AsmParser where it gets1025// expanded to real instructions immediately.1026let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32,1027 isCodeGenOnly = 0, isAsmParserOnly = 1 in1028def PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm_li:$imm), [],1029 "li", "$rd, $imm">;1030 1031def PseudoLB : PseudoLoad<"lb">;1032def PseudoLBU : PseudoLoad<"lbu">;1033def PseudoLH : PseudoLoad<"lh">;1034def PseudoLHU : PseudoLoad<"lhu">;1035def PseudoLW : PseudoLoad<"lw">;1036 1037def PseudoSB : PseudoStore<"sb">;1038def PseudoSH : PseudoStore<"sh">;1039def PseudoSW : PseudoStore<"sw">;1040 1041let Predicates = [IsRV64] in {1042def PseudoLWU : PseudoLoad<"lwu">;1043def PseudoLD : PseudoLoad<"ld">;1044def PseudoSD : PseudoStore<"sd">;1045} // Predicates = [IsRV64]1046 1047def : InstAlias<"nop", (ADDI X0, X0, 0), 3>;1048def : InstAlias<"li $rd, $imm", (ADDI GPR:$rd, X0, simm12_lo:$imm), 2>;1049def : InstAlias<"mv $rd, $rs", (ADDI GPR:$rd, GPR:$rs, 0)>;1050 1051def : InstAlias<"not $rd, $rs", (XORI GPR:$rd, GPR:$rs, -1)>;1052def : InstAlias<"neg $rd, $rs", (SUB GPR:$rd, X0, GPR:$rs)>;1053 1054let Predicates = [IsRV64] in {1055def : InstAlias<"negw $rd, $rs", (SUBW GPR:$rd, X0, GPR:$rs)>;1056def : InstAlias<"sext.w $rd, $rs", (ADDIW GPR:$rd, GPR:$rs, 0)>;1057} // Predicates = [IsRV64]1058 1059def : InstAlias<"seqz $rd, $rs", (SLTIU GPR:$rd, GPR:$rs, 1)>;1060def : InstAlias<"snez $rd, $rs", (SLTU GPR:$rd, X0, GPR:$rs)>;1061def : InstAlias<"sltz $rd, $rs", (SLT GPR:$rd, GPR:$rs, X0)>;1062def : InstAlias<"sgtz $rd, $rs", (SLT GPR:$rd, X0, GPR:$rs)>;1063 1064// sgt/sgtu are recognised by the GNU assembler but the canonical slt/sltu1065// form will always be printed. Therefore, set a zero weight.1066def : InstAlias<"sgt $rd, $rs, $rt", (SLT GPR:$rd, GPR:$rt, GPR:$rs), 0>;1067def : InstAlias<"sgtu $rd, $rs, $rt", (SLTU GPR:$rd, GPR:$rt, GPR:$rs), 0>;1068 1069def : InstAlias<"beqz $rs, $offset",1070 (BEQ GPR:$rs, X0, bare_simm13_lsb0:$offset)>;1071def : InstAlias<"bnez $rs, $offset",1072 (BNE GPR:$rs, X0, bare_simm13_lsb0:$offset)>;1073def : InstAlias<"blez $rs, $offset",1074 (BGE X0, GPR:$rs, bare_simm13_lsb0:$offset)>;1075def : InstAlias<"bgez $rs, $offset",1076 (BGE GPR:$rs, X0, bare_simm13_lsb0:$offset)>;1077def : InstAlias<"bltz $rs, $offset",1078 (BLT GPR:$rs, X0, bare_simm13_lsb0:$offset)>;1079def : InstAlias<"bgtz $rs, $offset",1080 (BLT X0, GPR:$rs, bare_simm13_lsb0:$offset)>;1081 1082// Always output the canonical mnemonic for the pseudo branch instructions.1083// The GNU tools emit the canonical mnemonic for the branch pseudo instructions1084// as well (e.g. "bgt" will be recognised by the assembler but never printed by1085// objdump). Match this behaviour by setting a zero weight.1086def : InstAlias<"bgt $rs, $rt, $offset",1087 (BLT GPR:$rt, GPR:$rs, bare_simm13_lsb0:$offset), 0>;1088def : InstAlias<"ble $rs, $rt, $offset",1089 (BGE GPR:$rt, GPR:$rs, bare_simm13_lsb0:$offset), 0>;1090def : InstAlias<"bgtu $rs, $rt, $offset",1091 (BLTU GPR:$rt, GPR:$rs, bare_simm13_lsb0:$offset), 0>;1092def : InstAlias<"bleu $rs, $rt, $offset",1093 (BGEU GPR:$rt, GPR:$rs, bare_simm13_lsb0:$offset), 0>;1094 1095def : InstAlias<"j $offset", (JAL X0, simm21_lsb0_jal:$offset)>;1096def : InstAlias<"jal $offset", (JAL X1, simm21_lsb0_jal:$offset)>;1097 1098// Non-zero offset aliases of "jalr" are the lowest weight, followed by the1099// two-register form, then the one-register forms and finally "ret".1100def : InstAlias<"jr $rs", (JALR X0, GPR:$rs, 0), 3>;1101def : InstAlias<"jr ${offset}(${rs})", (JALR X0, GPR:$rs, simm12_lo:$offset)>;1102def : InstAlias<"jalr $rs", (JALR X1, GPR:$rs, 0), 3>;1103def : InstAlias<"jalr ${offset}(${rs})", (JALR X1, GPR:$rs, simm12_lo:$offset)>;1104def : InstAlias<"jalr $rd, $rs", (JALR GPR:$rd, GPR:$rs, 0), 2>;1105def : InstAlias<"ret", (JALR X0, X1, 0), 4>;1106 1107// Non-canonical forms for jump targets also accepted by the assembler.1108def : InstAlias<"jr $rs, $offset", (JALR X0, GPR:$rs, simm12_lo:$offset), 0>;1109def : InstAlias<"jalr $rs, $offset", (JALR X1, GPR:$rs, simm12_lo:$offset), 0>;1110def : InstAlias<"jalr $rd, $rs, $offset", (JALR GPR:$rd, GPR:$rs, simm12_lo:$offset), 0>;1111def : InstAlias<"jr (${rs})", (JALR X0, GPR:$rs, 0), 0>;1112def : InstAlias<"jalr (${rs})", (JALR X1, GPR:$rs, 0), 0>;1113def : InstAlias<"jalr $rd, (${rs})", (JALR GPR:$rd, GPR:$rs, 0), 0>;1114 1115def : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw1116 1117let Predicates = [HasStdExtZihintpause] in1118def : InstAlias<"pause", (FENCE 0x1, 0x0)>; // 0x1 == w1119 1120def : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, INSTRET.Encoding, X0), 2>;1121def : InstAlias<"rdcycle $rd", (CSRRS GPR:$rd, CYCLE.Encoding, X0), 2>;1122def : InstAlias<"rdtime $rd", (CSRRS GPR:$rd, TIME.Encoding, X0), 2>;1123 1124let Predicates = [IsRV32] in {1125def : InstAlias<"rdinstreth $rd", (CSRRS GPR:$rd, INSTRETH.Encoding, X0), 2>;1126def : InstAlias<"rdcycleh $rd", (CSRRS GPR:$rd, CYCLEH.Encoding, X0), 2>;1127def : InstAlias<"rdtimeh $rd", (CSRRS GPR:$rd, TIMEH.Encoding, X0), 2>;1128} // Predicates = [IsRV32]1129 1130def : InstAlias<"csrr $rd, $csr", (CSRRS GPR:$rd, csr_sysreg:$csr, X0)>;1131def : InstAlias<"csrw $csr, $rs", (CSRRW X0, csr_sysreg:$csr, GPR:$rs)>;1132def : InstAlias<"csrs $csr, $rs", (CSRRS X0, csr_sysreg:$csr, GPR:$rs)>;1133def : InstAlias<"csrc $csr, $rs", (CSRRC X0, csr_sysreg:$csr, GPR:$rs)>;1134 1135def : InstAlias<"csrwi $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>;1136def : InstAlias<"csrsi $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>;1137def : InstAlias<"csrci $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>;1138 1139let EmitPriority = 0 in {1140def : InstAlias<"csrw $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>;1141def : InstAlias<"csrs $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>;1142def : InstAlias<"csrc $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>;1143 1144def : InstAlias<"csrrw $rd, $csr, $imm", (CSRRWI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>;1145def : InstAlias<"csrrs $rd, $csr, $imm", (CSRRSI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>;1146def : InstAlias<"csrrc $rd, $csr, $imm", (CSRRCI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>;1147}1148 1149def : InstAlias<"sfence.vma", (SFENCE_VMA X0, X0), 2>;1150def : InstAlias<"sfence.vma $rs", (SFENCE_VMA GPR:$rs, X0)>;1151 1152def : InstAlias<"hfence.gvma", (HFENCE_GVMA X0, X0), 2>;1153def : InstAlias<"hfence.gvma $rs", (HFENCE_GVMA GPR:$rs, X0)>;1154 1155def : InstAlias<"hfence.vvma", (HFENCE_VVMA X0, X0), 2>;1156def : InstAlias<"hfence.vvma $rs", (HFENCE_VVMA GPR:$rs, X0)>;1157 1158let Predicates = [HasStdExtZihintntl] in {1159 def : InstAlias<"ntl.p1", (ADD X0, X0, X2)>;1160 def : InstAlias<"ntl.pall", (ADD X0, X0, X3)>;1161 def : InstAlias<"ntl.s1", (ADD X0, X0, X4)>;1162 def : InstAlias<"ntl.all", (ADD X0, X0, X5)>;1163} // Predicates = [HasStdExtZihintntl]1164 1165let EmitPriority = 0 in {1166def : InstAlias<"lb $rd, (${rs1})",1167 (LB GPR:$rd, GPR:$rs1, 0)>;1168def : InstAlias<"lh $rd, (${rs1})",1169 (LH GPR:$rd, GPR:$rs1, 0)>;1170def : InstAlias<"lw $rd, (${rs1})",1171 (LW GPR:$rd, GPR:$rs1, 0)>;1172def : InstAlias<"lbu $rd, (${rs1})",1173 (LBU GPR:$rd, GPR:$rs1, 0)>;1174def : InstAlias<"lhu $rd, (${rs1})",1175 (LHU GPR:$rd, GPR:$rs1, 0)>;1176 1177def : InstAlias<"sb $rs2, (${rs1})",1178 (SB GPR:$rs2, GPR:$rs1, 0)>;1179def : InstAlias<"sh $rs2, (${rs1})",1180 (SH GPR:$rs2, GPR:$rs1, 0)>;1181def : InstAlias<"sw $rs2, (${rs1})",1182 (SW GPR:$rs2, GPR:$rs1, 0)>;1183 1184def : InstAlias<"add $rd, $rs1, $imm12",1185 (ADDI GPR:$rd, GPR:$rs1, simm12_lo:$imm12)>;1186def : InstAlias<"and $rd, $rs1, $imm12",1187 (ANDI GPR:$rd, GPR:$rs1, simm12_lo:$imm12)>;1188def : InstAlias<"xor $rd, $rs1, $imm12",1189 (XORI GPR:$rd, GPR:$rs1, simm12_lo:$imm12)>;1190def : InstAlias<"or $rd, $rs1, $imm12",1191 (ORI GPR:$rd, GPR:$rs1, simm12_lo:$imm12)>;1192def : InstAlias<"sll $rd, $rs1, $shamt",1193 (SLLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;1194def : InstAlias<"srl $rd, $rs1, $shamt",1195 (SRLI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;1196def : InstAlias<"sra $rd, $rs1, $shamt",1197 (SRAI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;1198let Predicates = [IsRV64] in {1199def : InstAlias<"lwu $rd, (${rs1})",1200 (LWU GPR:$rd, GPR:$rs1, 0)>;1201def : InstAlias<"ld $rd, (${rs1})",1202 (LD GPR:$rd, GPR:$rs1, 0)>;1203def : InstAlias<"sd $rs2, (${rs1})",1204 (SD GPR:$rs2, GPR:$rs1, 0)>;1205 1206def : InstAlias<"addw $rd, $rs1, $imm12",1207 (ADDIW GPR:$rd, GPR:$rs1, simm12_lo:$imm12)>;1208def : InstAlias<"sllw $rd, $rs1, $shamt",1209 (SLLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>;1210def : InstAlias<"srlw $rd, $rs1, $shamt",1211 (SRLIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>;1212def : InstAlias<"sraw $rd, $rs1, $shamt",1213 (SRAIW GPR:$rd, GPR:$rs1, uimm5:$shamt)>;1214} // Predicates = [IsRV64]1215def : InstAlias<"slt $rd, $rs1, $imm12",1216 (SLTI GPR:$rd, GPR:$rs1, simm12_lo:$imm12)>;1217def : InstAlias<"sltu $rd, $rs1, $imm12",1218 (SLTIU GPR:$rd, GPR:$rs1, simm12_lo:$imm12)>;1219}1220 1221def : MnemonicAlias<"move", "mv">;1222 1223// The SCALL and SBREAK instructions were renamed to ECALL and EBREAK in1224// version 2.1 of the user-level ISA. Like the GNU toolchain, we still accept1225// the old name for backwards compatibility.1226def : MnemonicAlias<"scall", "ecall">;1227def : MnemonicAlias<"sbreak", "ebreak">;1228 1229def : InstAlias<"zext.b $rd, $rs", (ANDI GPR:$rd, GPR:$rs, 0xFF)>;1230 1231let Predicates = [HasStdExtZicfilp] in {1232def : InstAlias<"lpad $imm20", (AUIPC X0, uimm20:$imm20)>;1233}1234 1235//===----------------------------------------------------------------------===//1236// .insn directive instructions1237//===----------------------------------------------------------------------===//1238 1239def AnyRegOperand : AsmOperandClass {1240 let Name = "AnyRegOperand";1241 let RenderMethod = "addRegOperands";1242 let PredicateMethod = "isAnyReg";1243}1244 1245def AnyReg : Operand<XLenVT> {1246 let OperandType = "OPERAND_REGISTER";1247 let ParserMatchClass = AnyRegOperand;1248}1249 1250// isCodeGenOnly = 1 to hide them from the tablegened assembly parser.1251let isCodeGenOnly = 1, hasSideEffects = 1, mayLoad = 1, mayStore = 1,1252 hasNoSchedulingInfo = 1 in {1253def Insn16 : RVInst16<(outs), (ins uimm16:$value), "", "", [], InstFormatOther> {1254 bits<16> value;1255 1256 let Inst{15-0} = value;1257 let AsmString = ".insn 0x2, $value";1258}1259def Insn32 : RVInst<(outs), (ins uimm32:$value), "", "", [], InstFormatOther> {1260 bits<32> value;1261 1262 let Inst{31-0} = value;1263 let AsmString = ".insn 0x4, $value";1264}1265def Insn48 : RVInst48<(outs), (ins uimm48:$value), "", "", [], InstFormatOther> {1266 bits<48> value;1267 let Inst{47-0} = value;1268 let AsmString = ".insn 0x6, $value";1269}1270def Insn64 : RVInst64<(outs), (ins uimm64:$value), "", "", [], InstFormatOther> {1271 bits<64> value;1272 let Inst{63-0} = value;1273 let AsmString = ".insn 0x8, $value";1274}1275} // isCodeGenOnly, hasSideEffects, mayLoad, mayStore, hasNoSchedulingInfo1276 1277// isCodeGenOnly = 1 to hide them from the tablegened assembly parser.1278let isCodeGenOnly = 1, hasSideEffects = 1, mayLoad = 1, mayStore = 1,1279 hasNoSchedulingInfo = 1 in {1280def InsnR : DirectiveInsnR<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$funct3,1281 uimm7:$funct7, AnyReg:$rs1,1282 AnyReg:$rs2),1283 "$opcode, $funct3, $funct7, $rd, $rs1, $rs2">;1284def InsnR4 : DirectiveInsnR4<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode,1285 uimm3:$funct3,1286 uimm2:$funct2,1287 AnyReg:$rs1, AnyReg:$rs2,1288 AnyReg:$rs3),1289 "$opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3">;1290def InsnI : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$funct3,1291 AnyReg:$rs1, simm12_lo:$imm12),1292 "$opcode, $funct3, $rd, $rs1, $imm12">;1293def InsnI_Mem : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode,1294 uimm3:$funct3,1295 AnyReg:$rs1,1296 simm12_lo:$imm12),1297 "$opcode, $funct3, $rd, ${imm12}(${rs1})">;1298def InsnB : DirectiveInsnB<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3,1299 AnyReg:$rs1, AnyReg:$rs2,1300 bare_simm13_lsb0:$imm12),1301 "$opcode, $funct3, $rs1, $rs2, $imm12">;1302def InsnU : DirectiveInsnU<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode,1303 uimm20_lui:$imm20),1304 "$opcode, $rd, $imm20">;1305def InsnJ : DirectiveInsnJ<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode,1306 simm21_lsb0_jal:$imm20),1307 "$opcode, $rd, $imm20">;1308def InsnS : DirectiveInsnS<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3,1309 AnyReg:$rs2, AnyReg:$rs1,1310 simm12_lo:$imm12),1311 "$opcode, $funct3, $rs2, ${imm12}(${rs1})">;1312} // isCodeGenOnly, hasSideEffects, mayLoad, mayStore, hasNoSchedulingInfo1313 1314// Use InstAliases to match these so that we can combine the insn and format1315// into a mnemonic to use as the key for the tablegened asm matcher table. The1316// parser will take care of creating these fake mnemonics and will only do it1317// for known formats.1318let EmitPriority = 0 in {1319def : InstAlias<".insn_r $opcode, $funct3, $funct7, $rd, $rs1, $rs2",1320 (InsnR AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm7:$funct7,1321 AnyReg:$rs1, AnyReg:$rs2)>;1322// Accept 4 register form of ".insn r" as alias for ".insn r4".1323def : InstAlias<".insn_r $opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3",1324 (InsnR4 AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm2:$funct2,1325 AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>;1326def : InstAlias<".insn_r4 $opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3",1327 (InsnR4 AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm2:$funct2,1328 AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>;1329def : InstAlias<".insn_i $opcode, $funct3, $rd, $rs1, $imm12",1330 (InsnI AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1,1331 simm12_lo:$imm12)>;1332def : InstAlias<".insn_i $opcode, $funct3, $rd, ${imm12}(${rs1})",1333 (InsnI_Mem AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3,1334 AnyReg:$rs1, simm12_lo:$imm12)>;1335def : InstAlias<".insn_i $opcode, $funct3, $rd, (${rs1})",1336 (InsnI_Mem AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3,1337 AnyReg:$rs1, 0)>;1338def : InstAlias<".insn_b $opcode, $funct3, $rs1, $rs2, $imm12",1339 (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1,1340 AnyReg:$rs2, bare_simm13_lsb0:$imm12)>;1341// Accept sb as an alias for b.1342def : InstAlias<".insn_sb $opcode, $funct3, $rs1, $rs2, $imm12",1343 (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1,1344 AnyReg:$rs2, bare_simm13_lsb0:$imm12)>;1345def : InstAlias<".insn_u $opcode, $rd, $imm20",1346 (InsnU AnyReg:$rd, uimm7_opcode:$opcode, uimm20_lui:$imm20)>;1347def : InstAlias<".insn_j $opcode, $rd, $imm20",1348 (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>;1349// Accept uj as an alias for j.1350def : InstAlias<".insn_uj $opcode, $rd, $imm20",1351 (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>;1352def : InstAlias<".insn_s $opcode, $funct3, $rs2, ${imm12}(${rs1})",1353 (InsnS uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs2,1354 AnyReg:$rs1, simm12_lo:$imm12)>;1355def : InstAlias<".insn_s $opcode, $funct3, $rs2, (${rs1})",1356 (InsnS uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs2,1357 AnyReg:$rs1, 0)>;1358}1359 1360//===----------------------------------------------------------------------===//1361// Pseudo-instructions and codegen patterns1362//1363// Naming convention: For 'generic' pattern classes, we use the naming1364// convention PatTy1Ty2. For pattern classes which offer a more complex1365// expansion, prefix the class name, e.g. BccPat.1366//===----------------------------------------------------------------------===//1367 1368/// Generic pattern classes1369 1370class PatGpr<SDPatternOperator OpNode, RVInst Inst, ValueType vt = XLenVT>1371 : Pat<(vt (OpNode (vt GPR:$rs1))), (Inst GPR:$rs1)>;1372class PatGprGpr<SDPatternOperator OpNode, RVInst Inst, ValueType vt = XLenVT>1373 : Pat<(vt (OpNode (vt GPR:$rs1), (vt GPR:$rs2))), (Inst GPR:$rs1, GPR:$rs2)>;1374 1375class PatGprImm<SDPatternOperator OpNode, RVInst Inst, ImmLeaf ImmType,1376 ValueType vt = XLenVT>1377 : Pat<(vt (OpNode (vt GPR:$rs1), ImmType:$imm)),1378 (Inst GPR:$rs1, ImmType:$imm)>;1379class PatGprSimm12<SDPatternOperator OpNode, RVInstI Inst>1380 : PatGprImm<OpNode, Inst, simm12_lo>;1381class PatGprUimmLog2XLen<SDPatternOperator OpNode, RVInstIShift Inst>1382 : PatGprImm<OpNode, Inst, uimmlog2xlen>;1383 1384/// Predicates1385 1386def assertsexti32 : PatFrag<(ops node:$src), (assertsext node:$src), [{1387 return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32);1388}]>;1389def sexti16 : ComplexPattern<XLenVT, 1, "selectSExtBits<16>">;1390 1391def sexti32 : ComplexPattern<i64, 1, "selectSExtBits<32>">;1392def gi_sexti32 : GIComplexOperandMatcher<s64, "selectSExtBits<32>">,1393 GIComplexPatternEquiv<sexti32>;1394 1395def assertzexti32 : PatFrag<(ops node:$src), (assertzext node:$src), [{1396 return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32);1397}]>;1398 1399def zexti32 : ComplexPattern<i64, 1, "selectZExtBits<32>">;1400def gi_zexti32 : GIComplexOperandMatcher<s64, "selectZExtBits<32>">,1401 GIComplexPatternEquiv<zexti32>;1402 1403def zexti16 : ComplexPattern<XLenVT, 1, "selectZExtBits<16>">;1404def gi_zexti16 : GIComplexOperandMatcher<s32, "selectZExtBits<16>">,1405 GIComplexPatternEquiv<zexti16>;1406 1407def zexti8 : ComplexPattern<XLenVT, 1, "selectZExtBits<8>">;1408def gi_zexti8 : GIComplexOperandMatcher<s32, "selectZExtBits<8>">,1409 GIComplexPatternEquiv<zexti8>;1410 1411def ext : PatFrags<(ops node:$A), [(sext node:$A), (zext node:$A)]>;1412 1413class binop_oneuse<SDPatternOperator operator>1414 : PatFrag<(ops node:$A, node:$B),1415 (operator node:$A, node:$B)> {1416 let HasOneUse = 1;1417}1418 1419def and_oneuse : binop_oneuse<and>;1420def mul_oneuse : binop_oneuse<mul>;1421 1422def mul_const_oneuse : PatFrag<(ops node:$A, node:$B),1423 (mul node:$A, node:$B), [{1424 if (auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1)))1425 return N1C->hasOneUse();1426 return false;1427}]>;1428 1429class unop_oneuse<SDPatternOperator operator>1430 : PatFrag<(ops node:$A),1431 (operator node:$A)> {1432 let HasOneUse = 1;1433}1434 1435def sext_oneuse : unop_oneuse<sext>;1436def zext_oneuse : unop_oneuse<zext>;1437def anyext_oneuse : unop_oneuse<anyext>;1438def ext_oneuse : unop_oneuse<ext>;1439def fpext_oneuse : unop_oneuse<any_fpextend>;1440 1441def 33signbits_node : PatLeaf<(i64 GPR:$src), [{1442 return CurDAG->ComputeNumSignBits(Op) > 32;1443}]>;1444 1445class immop_oneuse<ImmLeaf leaf> : PatLeaf<(leaf), [{1446 return N->hasOneUse();1447}]> {1448 let GISelPredicateCode = [{1449 return MRI.hasOneNonDBGUse(MI.getOperand(0).getReg());1450 }];1451}1452 1453/// Simple arithmetic operations1454 1455def : PatGprGpr<add, ADD>;1456def : PatGprSimm12<add, ADDI>;1457def : PatGprGpr<sub, SUB>;1458def : PatGprGpr<or, OR>;1459def : PatGprSimm12<or, ORI>;1460def : PatGprGpr<and, AND>;1461def : PatGprSimm12<and, ANDI>;1462def : PatGprGpr<xor, XOR>;1463def : PatGprSimm12<xor, XORI>;1464def : PatGprUimmLog2XLen<shl, SLLI>;1465def : PatGprUimmLog2XLen<srl, SRLI>;1466def : PatGprUimmLog2XLen<sra, SRAI>;1467 1468// Select 'or' as ADDI if the immediate bits are known to be 0 in $rs1. This1469// can improve compressibility.1470def riscv_or_disjoint : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{1471 return orDisjoint(N);1472}]>;1473def : PatGprSimm12<riscv_or_disjoint, ADDI>;1474 1475def add_like : PatFrags<(ops node:$lhs, node:$rhs),1476 [(riscv_or_disjoint node:$lhs, node:$rhs),1477 (add node:$lhs, node:$rhs)]>;1478 1479def riscv_xor_like : PatFrags<(ops node:$lhs, node:$rhs),1480 [(riscv_or_disjoint node:$lhs, node:$rhs),1481 (xor node:$lhs, node:$rhs)]>;1482 1483// negate of low bit can be done via two (compressible) shifts. The negate1484// is never compressible since rs1 and rd can't be the same register.1485def : Pat<(i32 (sub 0, (and_oneuse GPR:$rs, 1))),1486 (SRAI (i32 (SLLI $rs, 31)), 31)>, Requires<[IsRV32]>;1487def : Pat<(i64 (sub 0, (and_oneuse GPR:$rs, 1))),1488 (SRAI (i64 (SLLI $rs, 63)), 63)>, Requires<[IsRV64]>;1489 1490// AND with leading/trailing ones mask exceeding simm32/simm12.1491def : Pat<(i64 (and GPR:$rs, immop_oneuse<LeadingOnesMask>:$mask)),1492 (SLLI (i64 (SRLI $rs, (TrailingZeros imm:$mask))),1493 (TrailingZeros imm:$mask))>;1494def : Pat<(XLenVT (and GPR:$rs, immop_oneuse<TrailingOnesMask>:$mask)),1495 (SRLI (XLenVT (SLLI $rs, (XLenSubTrailingOnes imm:$mask))),1496 (XLenSubTrailingOnes imm:$mask))>;1497 1498// Match both a plain shift and one where the shift amount is masked (this is1499// typically introduced when the legalizer promotes the shift amount and1500// zero-extends it). For RISC-V, the mask is unnecessary as shifts in the base1501// ISA only read the least significant 5 bits (RV32I) or 6 bits (RV64I).1502def shiftMaskXLen : ComplexPattern<XLenVT, 1, "selectShiftMaskXLen", [], [], 0>;1503def shiftMask32 : ComplexPattern<i64, 1, "selectShiftMask32", [], [], 0>;1504// FIXME: This is labelled as handling 's32', however the ComplexPattern it1505// refers to handles both i32 and i64 based on the HwMode. Currently this LLT1506// parameter appears to be ignored so this pattern works for both, however we1507// should add a LowLevelTypeByHwMode, and use that to define our XLenLLT instead1508// here.1509def GIShiftMaskXLen :1510 GIComplexOperandMatcher<s32, "selectShiftMaskXLen">,1511 GIComplexPatternEquiv<shiftMaskXLen>;1512def GIShiftMask32 :1513 GIComplexOperandMatcher<s64, "selectShiftMask32">,1514 GIComplexPatternEquiv<shiftMask32>;1515 1516class PatGprShiftMaskXLen<SDPatternOperator OpNode, RVInst Inst>1517 : Pat<(OpNode GPR:$rs1, shiftMaskXLen:$rs2),1518 (Inst GPR:$rs1, shiftMaskXLen:$rs2)>;1519class PatGprShiftMask32<SDPatternOperator OpNode, RVInst Inst>1520 : Pat<(OpNode GPR:$rs1, shiftMask32:$rs2),1521 (Inst GPR:$rs1, shiftMask32:$rs2)>;1522 1523def : PatGprShiftMaskXLen<shl, SLL>;1524def : PatGprShiftMaskXLen<srl, SRL>;1525def : PatGprShiftMaskXLen<sra, SRA>;1526 1527// This is a special case of the ADD instruction used to facilitate the use of a1528// fourth operand to emit a relocation on a symbol relating to this instruction.1529// The relocation does not affect any bits of the instruction itself but is used1530// as a hint to the linker.1531let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in1532def PseudoAddTPRel : Pseudo<(outs GPR:$rd),1533 (ins GPR:$rs1, GPR:$rs2, tprel_add_symbol:$src), [],1534 "add", "$rd, $rs1, $rs2, $src">;1535 1536/// FrameIndex calculations1537 1538// Transforms frameindex -> tframeindex.1539def to_tframeindex : SDNodeXForm<frameindex, [{1540 return CurDAG->getTargetFrameIndex(N->getIndex(), N->getValueType(0));1541}]>;1542 1543def : GICustomOperandRenderer<"renderFrameIndex">,1544 GISDNodeXFormEquiv<to_tframeindex>;1545 1546def : Pat<(frameindex:$fi), (ADDI (iPTR (to_tframeindex $fi)), 0)>;1547 1548def : Pat<(add_like frameindex:$fi, simm12_lo:$offset),1549 (ADDI (iPTR (to_tframeindex $fi)), simm12_lo:$offset)>;1550 1551def GIAddrRegImm :1552 GIComplexOperandMatcher<s32, "selectAddrRegImm">,1553 GIComplexPatternEquiv<AddrRegImm>;1554 1555/// Stack probing1556 1557let hasSideEffects = 1, mayLoad = 1, mayStore = 1, isCodeGenOnly = 1,1558 Defs = [X2], Uses = [X2] in {1559// Probed stack allocation of a constant size, used in function prologues when1560// stack-clash protection is enabled.1561def PROBED_STACKALLOC : Pseudo<(outs),1562 (ins GPR:$target),1563 []>,1564 Sched<[]>;1565def PROBED_STACKALLOC_RVV : Pseudo<(outs),1566 (ins GPR:$target),1567 []>,1568 Sched<[]>;1569let usesCustomInserter = 1 in1570def PROBED_STACKALLOC_DYN : Pseudo<(outs),1571 (ins GPR:$target),1572 [(riscv_probed_alloca GPR:$target)]>,1573 Sched<[]>;1574}1575 1576/// HI and ADD_LO address nodes.1577 1578// Pseudo for a rematerializable LUI+ADDI sequence for loading an address.1579// It will be expanded after register allocation.1580// FIXME: The scheduling information does not reflect the multiple instructions.1581let Size = 8, isReMaterializable = 1 in1582def PseudoMovAddr : Pseudo<(outs GPR:$dst), (ins uimm20_lui:$hi, simm12_lo:$lo), []>,1583 Sched<[WriteIALU]>;1584 1585def riscv_hi_oneuse : unop_oneuse<riscv_hi>;1586def addr_hi_lo : PatFrag<(ops node:$hi, node:$lo),1587 (riscv_add_lo (riscv_hi_oneuse node:$hi), node:$lo)>;1588 1589def : Pat<(addr_hi_lo tglobaladdr:$hi, tglobaladdr:$lo),1590 (PseudoMovAddr tglobaladdr:$hi, tglobaladdr:$lo)>;1591def : Pat<(addr_hi_lo tblockaddress:$hi, tblockaddress:$lo),1592 (PseudoMovAddr tblockaddress:$hi, tblockaddress:$lo)>;1593def : Pat<(addr_hi_lo tjumptable:$hi, tjumptable:$lo),1594 (PseudoMovAddr tjumptable:$hi, tjumptable:$lo)>;1595def : Pat<(addr_hi_lo tconstpool:$hi, tconstpool:$lo),1596 (PseudoMovAddr tconstpool:$hi, tconstpool:$lo)>;1597 1598def : Pat<(riscv_hi tglobaladdr:$in), (LUI tglobaladdr:$in)>;1599def : Pat<(riscv_hi tblockaddress:$in), (LUI tblockaddress:$in)>;1600def : Pat<(riscv_hi tjumptable:$in), (LUI tjumptable:$in)>;1601def : Pat<(riscv_hi tconstpool:$in), (LUI tconstpool:$in)>;1602 1603def : Pat<(riscv_add_lo GPR:$hi, tglobaladdr:$lo),1604 (ADDI GPR:$hi, tglobaladdr:$lo)>;1605def : Pat<(riscv_add_lo GPR:$hi, tblockaddress:$lo),1606 (ADDI GPR:$hi, tblockaddress:$lo)>;1607def : Pat<(riscv_add_lo GPR:$hi, tjumptable:$lo),1608 (ADDI GPR:$hi, tjumptable:$lo)>;1609def : Pat<(riscv_add_lo GPR:$hi, tconstpool:$lo),1610 (ADDI GPR:$hi, tconstpool:$lo)>;1611 1612/// TLS address nodes.1613 1614def : Pat<(riscv_hi tglobaltlsaddr:$in), (LUI tglobaltlsaddr:$in)>;1615def : Pat<(riscv_add_tprel GPR:$rs1, GPR:$rs2, tglobaltlsaddr:$src),1616 (PseudoAddTPRel GPR:$rs1, GPR:$rs2, tglobaltlsaddr:$src)>;1617def : Pat<(riscv_add_lo GPR:$src, tglobaltlsaddr:$lo),1618 (ADDI GPR:$src, tglobaltlsaddr:$lo)>;1619 1620/// Setcc1621 1622def : PatGprGpr<setlt, SLT>;1623def : PatGprSimm12<setlt, SLTI>;1624def : PatGprGpr<setult, SLTU>;1625def : PatGprSimm12<setult, SLTIU>;1626 1627// RISC-V doesn't have general instructions for integer setne/seteq, but we can1628// check for equality with 0. These ComplexPatterns rewrite the setne/seteq into1629// something that can be compared with 0.1630// These ComplexPatterns must be used in pairs.1631def riscv_setne : ComplexPattern<XLenVT, 1, "selectSETNE", [setcc]>;1632def riscv_seteq : ComplexPattern<XLenVT, 1, "selectSETEQ", [setcc]>;1633 1634// Define pattern expansions for setcc operations that aren't directly1635// handled by a RISC-V instruction.1636def : Pat<(riscv_seteq (XLenVT GPR:$rs1)), (SLTIU GPR:$rs1, 1)>;1637def : Pat<(riscv_setne (XLenVT GPR:$rs1)), (SLTU (XLenVT X0), GPR:$rs1)>;1638def : Pat<(XLenVT (setne (XLenVT GPR:$rs1), -1)), (SLTIU GPR:$rs1, -1)>;1639def : Pat<(XLenVT (seteq (XLenVT (and GPR:$rs, immop_oneuse<TrailingOnesMask>:$mask)), 0)),1640 (SLTIU (XLenVT (SLLI GPR:$rs, (XLenSubTrailingOnes imm:$mask))), 1)>;1641def : Pat<(XLenVT (setne (XLenVT (and GPR:$rs, immop_oneuse<TrailingOnesMask>:$mask)), 0)),1642 (SLTU (XLenVT X0), (XLenVT (SLLI GPR:$rs, (XLenSubTrailingOnes imm:$mask))))>;1643 1644def IntCCtoRISCVCC : SDNodeXForm<riscv_selectcc, [{1645 ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();1646 RISCVCC::CondCode BrCC = getRISCVCCForIntCC(CC);1647 return CurDAG->getTargetConstant(BrCC, SDLoc(N), Subtarget->getXLenVT());1648}]>;1649 1650def riscv_selectcc_frag : PatFrag<(ops node:$lhs, node:$rhs, node:$cc,1651 node:$truev, node:$falsev),1652 (riscv_selectcc node:$lhs, node:$rhs,1653 node:$cc, node:$truev,1654 node:$falsev), [{}],1655 IntCCtoRISCVCC>;1656 1657multiclass SelectCC_GPR_rrirr<DAGOperand valty, ValueType vt,1658 ValueType cmpvt = XLenVT> {1659 let usesCustomInserter = 1 in1660 def _Using_CC_GPR : Pseudo<(outs valty:$dst),1661 (ins GPR:$lhs, GPR:$rhs, cond_code:$cc,1662 valty:$truev, valty:$falsev),1663 [(set valty:$dst,1664 (riscv_selectcc_frag:$cc (cmpvt GPR:$lhs), GPR:$rhs, cond,1665 (vt valty:$truev), valty:$falsev))]>;1666 // Explicitly select 0 in the condition to X0. The register coalescer doesn't1667 // always do it.1668 def : Pat<(riscv_selectcc_frag:$cc (cmpvt GPR:$lhs), 0, cond, (vt valty:$truev),1669 valty:$falsev),1670 (!cast<Instruction>(NAME#"_Using_CC_GPR") GPR:$lhs, (XLenVT X0),1671 (IntCCtoRISCVCC $cc), valty:$truev, valty:$falsev)>;1672}1673 1674let Predicates = [NoConditionalMoveFusion] in1675defm Select_GPR : SelectCC_GPR_rrirr<GPR, XLenVT>;1676 1677class SelectCompressOpt<CondCode Cond>1678 : Pat<(riscv_selectcc_frag:$select (XLenVT GPR:$lhs), simm12_no6:$Constant, Cond,1679 (XLenVT GPR:$truev), GPR:$falsev),1680 (Select_GPR_Using_CC_GPR (XLenVT (ADDI GPR:$lhs, (NegImm simm12_lo:$Constant))), (XLenVT X0),1681 (IntCCtoRISCVCC $select), GPR:$truev, GPR:$falsev)>;1682 1683def OptForMinSize : Predicate<"MF ? MF->getFunction().hasMinSize() : false">;1684 1685let Predicates = [HasStdExtC, OptForMinSize] in {1686 def : SelectCompressOpt<SETEQ>;1687 def : SelectCompressOpt<SETNE>;1688}1689 1690multiclass SelectCC_GPR_riirr<DAGOperand valty, DAGOperand imm> {1691 let usesCustomInserter = 1 in1692 def Select_# valty #_Using_ # NAME1693 : Pseudo<(outs valty:$dst),1694 (ins valty:$lhs, imm:$imm, cond_code:$cc,1695 valty:$truev, valty:$falsev), []>;1696}1697 1698let Predicates = [IsRV32] in {1699def : Pat<(i32 (setlt (i32 GPR:$rs1), 0)), (SRLI GPR:$rs1, 31)>; // compressible1700}1701let Predicates = [IsRV64] in {1702def : Pat<(i64 (setlt (i64 GPR:$rs1), 0)), (SRLI GPR:$rs1, 63)>; // compressible1703def : Pat<(i64 (setlt (sext_inreg GPR:$rs1, i32), 0)), (SRLIW GPR:$rs1, 31)>;1704}1705 1706/// Branches and jumps1707 1708// Match `riscv_brcc` and lower to the appropriate RISC-V branch instruction.1709multiclass BccPat<CondCode Cond, RVInstB Inst> {1710 def : Pat<(riscv_brcc (XLenVT GPR:$rs1), GPR:$rs2, Cond, bb:$imm12),1711 (Inst GPR:$rs1, GPR:$rs2, bare_simm13_lsb0_bb:$imm12)>;1712 // Explicitly select 0 to X0. The register coalescer doesn't always do it.1713 def : Pat<(riscv_brcc (XLenVT GPR:$rs1), 0, Cond, bb:$imm12),1714 (Inst GPR:$rs1, (XLenVT X0), bare_simm13_lsb0_bb:$imm12)>;1715}1716 1717class BrccCompressOpt<CondCode Cond, RVInstB Inst>1718 : Pat<(riscv_brcc GPR:$lhs, simm12_no6:$Constant, Cond, bb:$place),1719 (Inst (XLenVT (ADDI GPR:$lhs, (NegImm simm12_lo:$Constant))),1720 (XLenVT X0), bb:$place)>;1721 1722defm : BccPat<SETEQ, BEQ>;1723defm : BccPat<SETNE, BNE>;1724defm : BccPat<SETLT, BLT>;1725defm : BccPat<SETGE, BGE>;1726defm : BccPat<SETULT, BLTU>;1727defm : BccPat<SETUGE, BGEU>;1728 1729let Predicates = [HasStdExtZca, OptForMinSize] in {1730 def : BrccCompressOpt<SETEQ, BEQ>;1731 def : BrccCompressOpt<SETNE, BNE>;1732}1733 1734class LongBccPseudo : Pseudo<(outs),1735 (ins GPR:$rs1, GPR:$rs2, simm21_lsb0_jal:$imm20),1736 []> {1737 let Size = 8;1738 let isBarrier = 1;1739 let isBranch = 1;1740 let hasSideEffects = 0;1741 let mayStore = 0;1742 let mayLoad = 0;1743 let isAsmParserOnly = 1;1744 let hasNoSchedulingInfo = 1;1745}1746 1747def PseudoLongBEQ : LongBccPseudo;1748def PseudoLongBNE : LongBccPseudo;1749def PseudoLongBLT : LongBccPseudo;1750def PseudoLongBGE : LongBccPseudo;1751def PseudoLongBLTU : LongBccPseudo;1752def PseudoLongBGEU : LongBccPseudo;1753 1754let isBarrier = 1, isBranch = 1, isTerminator = 1 in1755def PseudoBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>,1756 PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>;1757 1758let Predicates = [NoStdExtZicfilp],1759 isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in1760def PseudoBRIND : Pseudo<(outs), (ins GPRJALR:$rs1, simm12_lo:$imm12), []>,1761 PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12_lo:$imm12)>;1762 1763let Predicates = [HasStdExtZicfilp],1764 isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in {1765def PseudoBRINDNonX7 : Pseudo<(outs), (ins GPRJALRNonX7:$rs1, simm12_lo:$imm12), []>,1766 PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12_lo:$imm12)>;1767def PseudoBRINDX7 : Pseudo<(outs), (ins GPRX7:$rs1, simm12_lo:$imm12), []>,1768 PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12_lo:$imm12)>;1769}1770 1771// For Zicfilp, need to avoid using X7/T2 for indirect branches which need1772// landing pad.1773let Predicates = [HasStdExtZicfilp] in {1774def : Pat<(brind GPRJALRNonX7:$rs1), (PseudoBRINDNonX7 GPRJALRNonX7:$rs1, 0)>;1775def : Pat<(brind (add GPRJALRNonX7:$rs1, simm12_lo:$imm12)),1776 (PseudoBRINDNonX7 GPRJALRNonX7:$rs1, simm12_lo:$imm12)>;1777 1778def : Pat<(riscv_sw_guarded_brind GPRX7:$rs1), (PseudoBRINDX7 GPRX7:$rs1, 0)>;1779def : Pat<(riscv_sw_guarded_brind (add GPRX7:$rs1, simm12_lo:$imm12)),1780 (PseudoBRINDX7 GPRX7:$rs1, simm12_lo:$imm12)>;1781}1782 1783let Predicates = [NoStdExtZicfilp] in {1784def : Pat<(brind GPRJALR:$rs1), (PseudoBRIND GPRJALR:$rs1, 0)>;1785def : Pat<(brind (add GPRJALR:$rs1, simm12_lo:$imm12)),1786 (PseudoBRIND GPRJALR:$rs1, simm12_lo:$imm12)>;1787}1788 1789// PseudoCALLReg is a generic pseudo instruction for calls which will eventually1790// expand to auipc and jalr while encoding, with any given register used as the1791// destination.1792// Define AsmString to print "call" when compile with -S flag.1793// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction.1794let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, Size = 8, hasSideEffects = 0,1795 mayStore = 0, mayLoad = 0 in1796def PseudoCALLReg : Pseudo<(outs GPR:$rd), (ins call_symbol:$func), [],1797 "call", "$rd, $func">,1798 Sched<[WriteIALU, WriteJalr, ReadJalr]>;1799 1800// PseudoCALL is a pseudo instruction which will eventually expand to auipc1801// and jalr while encoding. This is desirable, as an auipc+jalr pair with1802// R_RISCV_CALL and R_RISCV_RELAX relocations can be be relaxed by the linker1803// if the offset fits in a signed 21-bit immediate.1804// Define AsmString to print "call" when compile with -S flag.1805// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction.1806let isCall = 1, Defs = [X1], isCodeGenOnly = 0, Size = 8 in1807def PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), [],1808 "call", "$func">,1809 Sched<[WriteIALU, WriteJalr, ReadJalr]>;1810 1811def : Pat<(riscv_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>;1812def : Pat<(riscv_call texternalsym:$func), (PseudoCALL texternalsym:$func)>;1813 1814def : Pat<(riscv_sret_glue), (SRET)>;1815def : Pat<(riscv_mret_glue), (MRET)>;1816let Predicates = [HasStdExtSmrnmi] in1817def : Pat<(riscv_mnret_glue), (MNRET)>;1818 1819let isCall = 1, Defs = [X1] in {1820let Predicates = [NoStdExtZicfilp] in1821def PseudoCALLIndirect : Pseudo<(outs), (ins GPRJALR:$rs1),1822 [(riscv_call GPRJALR:$rs1)]>,1823 PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>;1824let Predicates = [HasStdExtZicfilp] in {1825def PseudoCALLIndirectNonX7 : Pseudo<(outs), (ins GPRJALRNonX7:$rs1),1826 [(riscv_call GPRJALRNonX7:$rs1)]>,1827 PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>;1828// For large code model, non-indirect calls could be software-guarded1829def PseudoCALLIndirectX7 : Pseudo<(outs), (ins GPRX7:$rs1),1830 [(riscv_sw_guarded_call GPRX7:$rs1)]>,1831 PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>;1832}1833}1834 1835let isBarrier = 1, isReturn = 1, isTerminator = 1 in1836def PseudoRET : Pseudo<(outs), (ins), [(riscv_ret_glue)]>,1837 PseudoInstExpansion<(JALR X0, X1, 0)>;1838 1839// PseudoTAIL is a pseudo instruction similar to PseudoCALL and will eventually1840// expand to auipc and jalr while encoding.1841// Define AsmString to print "tail" when compile with -S flag.1842let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2],1843 Size = 8, isCodeGenOnly = 0 in1844def PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), [],1845 "tail", "$dst">,1846 Sched<[WriteIALU, WriteJalr, ReadJalr]>;1847 1848let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in {1849let Predicates = [NoStdExtZicfilp] in1850def PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1),1851 [(riscv_tail GPRTC:$rs1)]>,1852 PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>;1853let Predicates = [HasStdExtZicfilp] in {1854def PseudoTAILIndirectNonX7 : Pseudo<(outs), (ins GPRTCNonX7:$rs1),1855 [(riscv_tail GPRTCNonX7:$rs1)]>,1856 PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>;1857// For large code model, non-indirect calls could be software-guarded1858def PseudoTAILIndirectX7 : Pseudo<(outs), (ins GPRX7:$rs1),1859 [(riscv_sw_guarded_tail GPRX7:$rs1)]>,1860 PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>;1861}1862}1863 1864def : Pat<(riscv_tail (iPTR tglobaladdr:$dst)),1865 (PseudoTAIL tglobaladdr:$dst)>;1866def : Pat<(riscv_tail (iPTR texternalsym:$dst)),1867 (PseudoTAIL texternalsym:$dst)>;1868 1869let isCall = 0, isBarrier = 1, isBranch = 1, isTerminator = 1, Size = 8,1870 isCodeGenOnly = 0, hasSideEffects = 0, mayStore = 0, mayLoad = 0 in1871def PseudoJump : Pseudo<(outs GPR:$rd), (ins pseudo_jump_symbol:$target), [],1872 "jump", "$target, $rd">,1873 Sched<[WriteIALU, WriteJalr, ReadJalr]>;1874 1875// Pseudo for a rematerializable constant materialization sequence.1876// This is an experimental feature enabled by1877// -riscv-use-rematerializable-movimm in RISCVISelDAGToDAG.cpp1878// It will be expanded after register allocation.1879// FIXME: The scheduling information does not reflect the multiple instructions.1880let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8,1881 isReMaterializable = 1 in1882def PseudoMovImm : Pseudo<(outs GPR:$dst), (ins i32imm:$imm), []>,1883 Sched<[WriteIALU]>;1884 1885let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0,1886 isAsmParserOnly = 1 in1887def PseudoLLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],1888 "lla", "$dst, $src">;1889 1890// Refer to comment on PseudoLI for explanation of Size=321891let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0,1892 isAsmParserOnly = 1 in1893def PseudoLLAImm : Pseudo<(outs GPR:$dst), (ins ixlenimm_li_restricted:$imm), [],1894 "lla", "$dst, $imm">;1895def : Pat<(riscv_lla tglobaladdr:$in), (PseudoLLA tglobaladdr:$in)>;1896def : Pat<(riscv_lla tblockaddress:$in), (PseudoLLA tblockaddress:$in)>;1897def : Pat<(riscv_lla tjumptable:$in), (PseudoLLA tjumptable:$in)>;1898def : Pat<(riscv_lla tconstpool:$in), (PseudoLLA tconstpool:$in)>;1899 1900let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0,1901 isAsmParserOnly = 1 in1902def PseudoLGA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],1903 "lga", "$dst, $src">;1904 1905let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0,1906 isAsmParserOnly = 1 in1907def PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],1908 "la", "$dst, $src">;1909 1910// Refer to comment on PseudoLI for explanation of Size=321911let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32,1912 isCodeGenOnly = 0, isAsmParserOnly = 1 in1913def PseudoLAImm : Pseudo<(outs GPR:$rd), (ins ixlenimm_li_restricted:$imm), [],1914 "la", "$rd, $imm">;1915 1916let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0,1917 isAsmParserOnly = 1 in1918def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],1919 "la.tls.ie", "$dst, $src">;1920 1921let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0,1922 isAsmParserOnly = 1 in1923def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],1924 "la.tls.gd", "$dst, $src">;1925 1926let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 32, isCodeGenOnly = 0 in1927def PseudoLA_TLSDESC : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],1928 "la.tlsdesc", "$dst, $src">;1929 1930def TLSDESCCallSymbol : AsmOperandClass {1931 let Name = "TLSDESCCallSymbol";1932 let RenderMethod = "addImmOperands";1933 let DiagnosticType = "InvalidTLSDESCCallSymbol";1934 let DiagnosticString = "operand must be a symbol with %tlsdesc_call specifier";1935 let ParserMethod = "parseOperandWithSpecifier";1936}1937 1938// A bare symbol with the %tlsdesc_call variant.1939def tlsdesc_call_symbol : Operand<XLenVT> {1940 let ParserMatchClass = TLSDESCCallSymbol;1941}1942// This is a special case of the JALR instruction used to facilitate the use of a1943// fourth operand to emit a relocation on a symbol relating to this instruction.1944// The relocation does not affect any bits of the instruction itself but is used1945// as a hint to the linker.1946let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, Size = 8, hasSideEffects = 0,1947 mayStore = 0, mayLoad = 0 in1948def PseudoTLSDESCCall : Pseudo<(outs GPR:$rd),1949 (ins GPR:$rs1, simm12_lo:$imm12, tlsdesc_call_symbol:$src), [],1950 "jalr", "$rd, ${imm12}(${rs1}), $src">,1951 Sched<[WriteJalr, ReadJalr]> {1952 let Defs = [X10];1953 let Uses = [X10];1954}1955 1956 1957/// Sign/Zero Extends1958 1959// There are single-instruction versions of these in Zbb, so disable these1960// Pseudos if that extension is present.1961let hasSideEffects = 0, mayLoad = 0,1962 mayStore = 0, isCodeGenOnly = 0, isAsmParserOnly = 1 in {1963def PseudoSEXT_B : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.b", "$rd, $rs">;1964def PseudoSEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.h", "$rd, $rs">;1965// rv64's sext.w is defined above, using InstAlias<"sext.w ...1966// zext.b is defined above, using InstAlias<"zext.b ...1967def PseudoZEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.h", "$rd, $rs">;1968} // hasSideEffects = 0, ...1969 1970let Predicates = [IsRV64], hasSideEffects = 0, mayLoad = 0, mayStore = 0,1971 isCodeGenOnly = 0, isAsmParserOnly = 1 in {1972def PseudoZEXT_W : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.w", "$rd, $rs">;1973} // Predicates = [IsRV64], ...1974 1975/// Loads1976 1977class LdPat<PatFrag LoadOp, RVInst Inst, ValueType vt = XLenVT,1978 ValueType PtrVT = XLenVT>1979 : Pat<(vt (LoadOp (AddrRegImm (PtrVT GPRMem:$rs1), simm12_lo:$imm12))),1980 (Inst GPRMem:$rs1, simm12_lo:$imm12)>;1981 1982def : LdPat<sextloadi8, LB>;1983def : LdPat<extloadi8, LBU>; // Prefer unsigned due to no c.lb in Zcb.1984def : LdPat<sextloadi16, LH>;1985def : LdPat<extloadi16, LH>;1986def : LdPat<load, LW, i32>, Requires<[IsRV32]>;1987def : LdPat<zextloadi8, LBU>;1988def : LdPat<zextloadi16, LHU>;1989 1990/// Stores1991 1992class StPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy,1993 ValueType vt, ValueType PtrVT = XLenVT>1994 : Pat<(StoreOp (vt StTy:$rs2), (AddrRegImm (PtrVT GPRMem:$rs1),1995 simm12_lo:$imm12)),1996 (Inst StTy:$rs2, GPRMem:$rs1, simm12_lo:$imm12)>;1997 1998def : StPat<truncstorei8, SB, GPR, XLenVT>;1999def : StPat<truncstorei16, SH, GPR, XLenVT>;2000def : StPat<store, SW, GPR, i32>, Requires<[IsRV32]>;2001 2002/// Fences2003 2004// Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set2005// Manual: Volume I.2006 2007// fence acquire -> fence r, rw2008def : Pat<(atomic_fence (XLenVT 4), (timm)), (FENCE 0b10, 0b11)>;2009// fence release -> fence rw, w2010def : Pat<(atomic_fence (XLenVT 5), (timm)), (FENCE 0b11, 0b1)>;2011// fence acq_rel -> fence.tso2012def : Pat<(atomic_fence (XLenVT 6), (timm)), (FENCE_TSO)>;2013// fence seq_cst -> fence rw, rw2014def : Pat<(atomic_fence (XLenVT 7), (timm)), (FENCE 0b11, 0b11)>;2015 2016// Lowering for atomic load and store is defined in RISCVInstrInfoA.td.2017// Although these are lowered to fence+load/store instructions defined in the2018// base RV32I/RV64I ISA, this lowering is only used when the A extension is2019// present. This is necessary as it isn't valid to mix __atomic_* libcalls2020// with inline atomic operations for the same object.2021 2022/// Access to system registers2023 2024// Helpers for defining specific operations. They are defined for each system2025// register separately. Side effect is not used because dependencies are2026// expressed via use-def properties.2027 2028class ReadSysReg<SysReg SR, list<Register> Regs>2029 : Pseudo<(outs GPR:$rd), (ins),2030 [(set GPR:$rd, (XLenVT (riscv_read_csr (XLenVT SR.Encoding))))]>,2031 PseudoInstExpansion<(CSRRS GPR:$rd, SR.Encoding, X0)> {2032 let hasSideEffects = 0;2033 let Uses = Regs;2034}2035 2036class WriteSysReg<SysReg SR, list<Register> Regs>2037 : Pseudo<(outs), (ins GPR:$val),2038 [(riscv_write_csr (XLenVT SR.Encoding), (XLenVT GPR:$val))]>,2039 PseudoInstExpansion<(CSRRW X0, SR.Encoding, GPR:$val)> {2040 let hasSideEffects = 0;2041 let Defs = Regs;2042}2043 2044class WriteSysRegImm<SysReg SR, list<Register> Regs>2045 : Pseudo<(outs), (ins uimm5:$val),2046 [(riscv_write_csr (XLenVT SR.Encoding), uimm5:$val)]>,2047 PseudoInstExpansion<(CSRRWI X0, SR.Encoding, uimm5:$val)> {2048 let hasSideEffects = 0;2049 let Defs = Regs;2050}2051 2052class SwapSysReg<SysReg SR, list<Register> Regs>2053 : Pseudo<(outs GPR:$rd), (ins GPR:$val),2054 [(set GPR:$rd, (riscv_swap_csr (XLenVT SR.Encoding), (XLenVT GPR:$val)))]>,2055 PseudoInstExpansion<(CSRRW GPR:$rd, SR.Encoding, GPR:$val)> {2056 let hasSideEffects = 0;2057 let Uses = Regs;2058 let Defs = Regs;2059}2060 2061class SwapSysRegImm<SysReg SR, list<Register> Regs>2062 : Pseudo<(outs GPR:$rd), (ins uimm5:$val),2063 [(set GPR:$rd, (XLenVT (riscv_swap_csr (XLenVT SR.Encoding), uimm5:$val)))]>,2064 PseudoInstExpansion<(CSRRWI GPR:$rd, SR.Encoding, uimm5:$val)> {2065 let hasSideEffects = 0;2066 let Uses = Regs;2067 let Defs = Regs;2068}2069 2070class ClearSysReg<SysReg SR, list<Register> Regs>2071 : Pseudo<(outs), (ins GPR:$val),2072 [(riscv_clear_csr (XLenVT SR.Encoding), (XLenVT GPR:$val))]>,2073 PseudoInstExpansion<(CSRRC X0, SR.Encoding, GPR:$val)> {2074 let hasSideEffects = 0;2075 let Uses = Regs;2076 let Defs = Regs;2077}2078 2079class ClearSysRegImm<SysReg SR, list<Register> Regs>2080 : Pseudo<(outs), (ins uimm5:$val),2081 [(riscv_clear_csr (XLenVT SR.Encoding), uimm5:$val)]>,2082 PseudoInstExpansion<(CSRRCI X0, SR.Encoding, uimm5:$val)> {2083 let hasSideEffects = 0;2084 let Uses = Regs;2085 let Defs = Regs;2086}2087 2088class SetSysReg<SysReg SR, list<Register> Regs>2089 : Pseudo<(outs), (ins GPR:$val),2090 [(riscv_set_csr (XLenVT SR.Encoding), (XLenVT GPR:$val))]>,2091 PseudoInstExpansion<(CSRRS X0, SR.Encoding, GPR:$val)> {2092 let hasSideEffects = 0;2093 let Uses = Regs;2094 let Defs = Regs;2095}2096 2097class SetSysRegImm<SysReg SR, list<Register> Regs>2098 : Pseudo<(outs), (ins uimm5:$val),2099 [(riscv_set_csr (XLenVT SR.Encoding), uimm5:$val)]>,2100 PseudoInstExpansion<(CSRRSI X0, SR.Encoding, uimm5:$val)> {2101 let hasSideEffects = 0;2102 let Uses = Regs;2103 let Defs = Regs;2104}2105 2106def ReadFRM : ReadSysReg<SysRegFRM, [FRM]>;2107let hasPostISelHook = 1 in {2108def WriteFRM : WriteSysReg<SysRegFRM, [FRM]>;2109def WriteFRMImm : WriteSysRegImm<SysRegFRM, [FRM]>;2110def SwapFRMImm : SwapSysRegImm<SysRegFRM, [FRM]>;2111}2112 2113def WriteVXRMImm : WriteSysRegImm<SysRegVXRM, [VXRM]>;2114 2115let hasSideEffects = true in {2116def ReadFFLAGS : ReadSysReg<SysRegFFLAGS, [FFLAGS]>;2117def WriteFFLAGS : WriteSysReg<SysRegFFLAGS, [FFLAGS]>;2118}2119 2120let hasPostISelHook = 1 in {2121def ReadFCSR : ReadSysReg<SysRegFCSR, [FRM, FFLAGS]>;2122def WriteFCSR : WriteSysReg<SysRegFCSR, [FRM, FFLAGS]>;2123def WriteFCSRImm : WriteSysRegImm<SysRegFCSR, [FRM, FFLAGS]>;2124def ClearFCSR : ClearSysReg<SysRegFCSR, [FRM, FFLAGS]>;2125def ClearFCSRImm : ClearSysRegImm<SysRegFCSR, [FRM, FFLAGS]>;2126def SetFCSR : SetSysReg<SysRegFCSR, [FRM, FFLAGS]>;2127def SetFCSRImm : SetSysRegImm<SysRegFCSR, [FRM, FFLAGS]>;2128}2129 2130/// Other pseudo-instructions2131 2132// Pessimistically assume the stack pointer will be clobbered2133let Defs = [X2], Uses = [X2] in {2134def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),2135 [(callseq_start timm:$amt1, timm:$amt2)]>;2136def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),2137 [(callseq_end timm:$amt1, timm:$amt2)]>;2138} // Defs = [X2], Uses = [X2]2139 2140/// RV64 patterns2141 2142let Predicates = [IsRV64, NoStdExtZba] in {2143def : Pat<(i64 (and GPR:$rs1, 0xffffffff)), (SRLI (i64 (SLLI GPR:$rs1, 32)), 32)>;2144 2145// If we're shifting a 32-bit zero extended value left by 0-31 bits, use 22146// shifts instead of 3. This can occur when unsigned is used to index an array.2147def : Pat<(i64 (shl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)),2148 (SRLI (i64 (SLLI GPR:$rs1, 32)), (ImmSubFrom32 uimm5:$shamt))>;2149} // Predicates = [IsRV64, NoStdExtZba]2150 2151class binop_allhusers<SDPatternOperator operator>2152 : PatFrag<(ops node:$lhs, node:$rhs),2153 (XLenVT (operator node:$lhs, node:$rhs)), [{2154 return hasAllHUsers(N);2155}]> {2156 let GISelPredicateCode = [{ return hasAllHUsers(MI); }];2157}2158 2159// PatFrag to allow ADDW/SUBW/MULW/SLLW to be selected from i64 add/sub/mul/shl2160// if only the lower 32 bits of their result is used.2161class binop_allwusers<SDPatternOperator operator>2162 : PatFrag<(ops node:$lhs, node:$rhs), (i64 (operator node:$lhs, node:$rhs)),2163 [{2164 return hasAllWUsers(N);2165}]> {2166 let GISelPredicateCode = [{ return hasAllWUsers(MI); }];2167}2168 2169def sexti32_allwusers : PatFrag<(ops node:$src),2170 (sext_inreg node:$src, i32), [{2171 return hasAllWUsers(N);2172}]>;2173 2174def ImmSExt32 : SDNodeXForm<imm, [{2175 return CurDAG->getTargetConstant(SignExtend64<32>(N->getSExtValue()),2176 SDLoc(N), N->getValueType(0));2177}]>;2178// Look for constants where the upper 32 bits are 0, but sign extending bit 312179// would be an simm12.2180def u32simm12 : ImmLeaf<XLenVT, [{2181 return isUInt<32>(Imm) && isInt<12>(SignExtend64<32>(Imm));2182}], ImmSExt32>;2183 2184let Predicates = [IsRV64] in {2185 2186def : Pat<(i64 (and GPR:$rs, immop_oneuse<LeadingOnesWMask>:$mask)),2187 (SLLI (i64 (SRLIW $rs, (TrailingZeros imm:$mask))),2188 (TrailingZeros imm:$mask))>;2189 2190/// sext and zext2191 2192// Sign extend is not needed if all users are W instructions.2193def : Pat<(sexti32_allwusers GPR:$rs1), (XLenVT GPR:$rs1)>;2194 2195def : Pat<(sext_inreg GPR:$rs1, i32), (ADDIW GPR:$rs1, 0)>;2196 2197/// ALU operations2198 2199def : Pat<(i64 (srl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)),2200 (SRLIW GPR:$rs1, uimm5:$shamt)>;2201def : Pat<(i64 (srl (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt)),2202 (SRLIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>;2203def : Pat<(sra (sext_inreg GPR:$rs1, i32), uimm5:$shamt),2204 (SRAIW GPR:$rs1, uimm5:$shamt)>;2205def : Pat<(i64 (sra (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt)),2206 (SRAIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>;2207 2208def : PatGprShiftMask32<riscv_sllw, SLLW>;2209def : PatGprShiftMask32<riscv_srlw, SRLW>;2210def : PatGprShiftMask32<riscv_sraw, SRAW>;2211 2212// Select W instructions if only the lower 32 bits of the result are used.2213def : PatGprGpr<binop_allwusers<add>, ADDW>;2214def : PatGprSimm12<binop_allwusers<add>, ADDIW>;2215def : PatGprImm<binop_allwusers<add>, ADDIW, u32simm12>;2216def : PatGprGpr<binop_allwusers<sub>, SUBW>;2217def : PatGprImm<binop_allwusers<shl>, SLLIW, uimm5>;2218 2219// If this is a shr of a value sign extended from i32, and all the users only2220// use the lower 32 bits, we can use an sraiw to remove the sext_inreg. This2221// occurs because SimplifyDemandedBits prefers srl over sra.2222def : Pat<(binop_allwusers<srl> (sext_inreg GPR:$rs1, i32), uimm5:$shamt),2223 (SRAIW GPR:$rs1, uimm5:$shamt)>;2224 2225// Use binop_allwusers to recover immediates that may have been broken by2226// SimplifyDemandedBits.2227def : Pat<(binop_allwusers<and> GPR:$rs1, 0xffffffff),2228 (COPY GPR:$rs1)>;2229def : PatGprImm<binop_allwusers<and>, ANDI, u32simm12>;2230def : PatGprImm<binop_allwusers<or>, ORI, u32simm12>;2231def : PatGprImm<binop_allwusers<xor>, XORI, u32simm12>;2232 2233// Select 'or' as ADDIW if the immediate bits are known to be 0 in $rs1 and2234// $rs1 is sign extended. This can improve compressibility. Using ADDIW gives2235// more power to RISCVOptWInstrs.2236def : Pat<(riscv_or_disjoint 33signbits_node:$rs1, simm12_lo:$imm),2237 (ADDIW $rs1, simm12_lo:$imm)>;2238 2239/// Loads2240 2241def : LdPat<sextloadi32, LW, i64>;2242def : LdPat<extloadi32, LW, i64>;2243def : LdPat<zextloadi32, LWU, i64>;2244def : LdPat<load, LD, i64>;2245 2246/// Stores2247 2248def : StPat<truncstorei32, SW, GPR, i64>;2249def : StPat<store, SD, GPR, i64>;2250} // Predicates = [IsRV64]2251 2252// On RV64, we can directly read these 64-bit counter CSRs.2253let Predicates = [IsRV64] in {2254/// readcyclecounter2255def : Pat<(i64 (readcyclecounter)), (CSRRS CYCLE.Encoding, (XLenVT X0))>;2256/// readsteadycounter2257def : Pat<(i64 (readsteadycounter)), (CSRRS TIME.Encoding, (XLenVT X0))>;2258}2259 2260// On RV32, ReadCounterWide will be expanded to the suggested loop reading both2261// halves of 64-bit counter CSRs.2262let Predicates = [IsRV32], usesCustomInserter = 1, hasNoSchedulingInfo = 1 in2263def ReadCounterWide : Pseudo<(outs GPR:$lo, GPR:$hi), (ins i32imm:$csr_lo, i32imm:$csr_hi),2264 [(set GPR:$lo, GPR:$hi,2265 (riscv_read_counter_wide csr_sysreg:$csr_lo, csr_sysreg:$csr_hi))],2266 "", "">;2267 2268/// traps2269 2270// We lower `trap` to `unimp`, as this causes a hard exception on nearly all2271// systems.2272def : Pat<(trap), (UNIMP)>;2273 2274// We lower `debugtrap` to `ebreak`, as this will get the attention of the2275// debugger if possible.2276def : Pat<(debugtrap), (EBREAK)>;2277 2278let Predicates = [IsRV64], Uses = [X5],2279 Defs = [X1, X6, X7, X28, X29, X30, X31], Size = 8 in2280def HWASAN_CHECK_MEMACCESS_SHORTGRANULES2281 : Pseudo<(outs), (ins GPRJALR:$ptr, i32imm:$accessinfo),2282 [(int_hwasan_check_memaccess_shortgranules (i64 X5), GPRJALR:$ptr,2283 (i32 timm:$accessinfo))]>;2284 2285// This gets lowered into a 20-byte instruction sequence (at most)2286let hasSideEffects = 0, mayLoad = 1, mayStore = 0,2287 Defs = [ X6, X7, X28, X29, X30, X31 ], Size = 20 in {2288def KCFI_CHECK2289 : Pseudo<(outs), (ins GPRJALR:$ptr, i32imm:$type), []>, Sched<[]>;2290}2291 2292/// Simple optimization2293def : Pat<(XLenVT (add GPR:$rs1, immop_oneuse<AddiPair>:$rs2)),2294 (ADDI (XLenVT (ADDI GPR:$rs1, (AddiPairImmLarge imm:$rs2))),2295 (AddiPairImmSmall imm:$rs2))>;2296 2297def negImm : ComplexPattern<i64, 1, "selectNegImm", [], [], 0>;2298 2299let Predicates = [IsRV64] in {2300// Select W instructions if only the lower 32-bits of the result are used.2301def : Pat<(binop_allwusers<add> GPR:$rs1, immop_oneuse<AddiPair>:$rs2),2302 (ADDIW (i64 (ADDIW GPR:$rs1, (AddiPairImmLarge imm:$rs2))),2303 (AddiPairImmSmall imm:$rs2))>;2304 2305// Select SUB if the negated constant is cheaper to materialize.2306def : Pat<(i64 (add GPR:$rs1, negImm:$rs2)), (SUB GPR:$rs1, negImm:$rs2)>;2307}2308 2309//===----------------------------------------------------------------------===//2310// Zihintpause2311//===----------------------------------------------------------------------===//2312 2313// Zihintpause2314let Predicates = [HasStdExtZihintpause] in2315def : Pat<(int_riscv_pause), (FENCE 0x1, 0x0)>;2316 2317//===----------------------------------------------------------------------===//2318// Standard extensions2319//===----------------------------------------------------------------------===//2320 2321// Multiply and Division2322include "RISCVInstrInfoM.td"2323 2324// Atomic2325include "RISCVInstrInfoA.td"2326include "RISCVInstrInfoZa.td"2327include "RISCVInstrInfoZalasr.td"2328 2329// Integer2330include "RISCVInstrInfoZimop.td"2331include "RISCVInstrInfoZicbo.td"2332include "RISCVInstrInfoZicond.td"2333include "RISCVInstrInfoZilsd.td"2334include "RISCVInstrInfoZibi.td"2335 2336// Scalar FP2337include "RISCVInstrInfoF.td"2338include "RISCVInstrInfoD.td"2339include "RISCVInstrInfoQ.td"2340include "RISCVInstrInfoZfh.td"2341include "RISCVInstrInfoZfbfmin.td"2342include "RISCVInstrInfoZfa.td"2343 2344// Scalar bitmanip and cryptography2345include "RISCVInstrInfoZb.td"2346include "RISCVInstrInfoZk.td"2347 2348// Vector2349include "RISCVInstrInfoV.td"2350include "RISCVInstrInfoZvk.td"2351include "RISCVInstrInfoZvqdotq.td"2352include "RISCVInstrInfoZvfofp8min.td"2353 2354// Packed SIMD2355include "RISCVInstrInfoP.td"2356 2357// Compressed2358include "RISCVInstrInfoC.td"2359include "RISCVInstrInfoZc.td"2360include "RISCVInstrInfoZcmop.td"2361include "RISCVInstrInfoZclsd.td"2362 2363// Control Flow Integriy, this requires Zimop/Zcmop2364include "RISCVInstrInfoZicfiss.td"2365 2366// Short Forward Branch2367include "RISCVInstrInfoSFB.td"2368 2369//===----------------------------------------------------------------------===//2370// Vendor extensions2371//===----------------------------------------------------------------------===//2372 2373include "RISCVInstrInfoXVentana.td"2374include "RISCVInstrInfoXTHead.td"2375include "RISCVInstrInfoXSf.td"2376include "RISCVInstrInfoXSfmm.td"2377include "RISCVInstrInfoXCV.td"2378include "RISCVInstrInfoXwch.td"2379include "RISCVInstrInfoXqci.td"2380include "RISCVInstrInfoXqccmp.td"2381include "RISCVInstrInfoXMips.td"2382include "RISCVInstrInfoXRivos.td"2383include "RISCVInstrInfoXAndes.td"2384include "RISCVInstrInfoXSpacemiT.td"2385 2386//===----------------------------------------------------------------------===//2387// Global ISel2388//===----------------------------------------------------------------------===//2389 2390include "RISCVInstrGISel.td"2391