xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfo.td (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric//===-- RISCVInstrInfo.td - Target Description for RISC-V --*- tablegen -*-===//
20b57cec5SDimitry Andric//
30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric//
70b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric//
90b57cec5SDimitry Andric// This file describes the RISC-V instructions in TableGen format.
100b57cec5SDimitry Andric//
110b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric// RISC-V specific DAG Nodes.
150b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
160b57cec5SDimitry Andric
170b57cec5SDimitry Andric// Target-independent type requirements, but with target-specific formats.
180b57cec5SDimitry Andricdef SDT_CallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>,
190b57cec5SDimitry Andric                                       SDTCisVT<1, i32>]>;
200b57cec5SDimitry Andricdef SDT_CallSeqEnd   : SDCallSeqEnd<[SDTCisVT<0, i32>,
210b57cec5SDimitry Andric                                     SDTCisVT<1, i32>]>;
220b57cec5SDimitry Andric
230b57cec5SDimitry Andric// Target-dependent type requirements.
240b57cec5SDimitry Andricdef SDT_RISCVCall     : SDTypeProfile<0, -1, [SDTCisVT<0, XLenVT>]>;
250b57cec5SDimitry Andricdef SDT_RISCVSelectCC : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>,
26349cc55cSDimitry Andric                                             SDTCisVT<3, OtherVT>,
270b57cec5SDimitry Andric                                             SDTCisSameAs<0, 4>,
280b57cec5SDimitry Andric                                             SDTCisSameAs<4, 5>]>;
29fe6060f1SDimitry Andricdef SDT_RISCVBrCC : SDTypeProfile<0, 4, [SDTCisSameAs<0, 1>,
30fe6060f1SDimitry Andric                                         SDTCisVT<2, OtherVT>,
31fe6060f1SDimitry Andric                                         SDTCisVT<3, OtherVT>]>;
32fe6060f1SDimitry Andricdef SDT_RISCVReadCSR  : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisInt<1>]>;
33fe6060f1SDimitry Andricdef SDT_RISCVWriteCSR : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisInt<1>]>;
34fe6060f1SDimitry Andricdef SDT_RISCVSwapCSR  : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisInt<1>,
35fe6060f1SDimitry Andric                                             SDTCisInt<2>]>;
36*0fca6ea1SDimitry Andricdef SDT_RISCVReadCounterWide : SDTypeProfile<2, 2, [SDTCisVT<0, i32>,
37*0fca6ea1SDimitry Andric                                                    SDTCisVT<1, i32>,
38*0fca6ea1SDimitry Andric                                                    SDTCisInt<2>,
39*0fca6ea1SDimitry Andric                                                    SDTCisInt<3>]>;
40fe6060f1SDimitry Andricdef SDT_RISCVIntUnaryOpW : SDTypeProfile<1, 1, [
41fe6060f1SDimitry Andric  SDTCisSameAs<0, 1>, SDTCisVT<0, i64>
42fe6060f1SDimitry Andric]>;
43fe6060f1SDimitry Andricdef SDT_RISCVIntBinOpW : SDTypeProfile<1, 2, [
44fe6060f1SDimitry Andric  SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64>
45fe6060f1SDimitry Andric]>;
46fe6060f1SDimitry Andricdef SDT_RISCVIntShiftDOpW : SDTypeProfile<1, 3, [
47fe6060f1SDimitry Andric  SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisVT<0, i64>, SDTCisVT<3, i64>
48fe6060f1SDimitry Andric]>;
490b57cec5SDimitry Andric
500b57cec5SDimitry Andric// Target-independent nodes, but with target-specific formats.
510b57cec5SDimitry Andricdef callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_CallSeqStart,
520b57cec5SDimitry Andric                           [SDNPHasChain, SDNPOutGlue]>;
530b57cec5SDimitry Andricdef callseq_end   : SDNode<"ISD::CALLSEQ_END", SDT_CallSeqEnd,
540b57cec5SDimitry Andric                           [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
550b57cec5SDimitry Andric
560b57cec5SDimitry Andric// Target-dependent nodes.
570b57cec5SDimitry Andricdef riscv_call      : SDNode<"RISCVISD::CALL", SDT_RISCVCall,
580b57cec5SDimitry Andric                             [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
590b57cec5SDimitry Andric                              SDNPVariadic]>;
6006c3fb27SDimitry Andricdef riscv_ret_glue  : SDNode<"RISCVISD::RET_GLUE", SDTNone,
610b57cec5SDimitry Andric                             [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
6206c3fb27SDimitry Andricdef riscv_sret_glue : SDNode<"RISCVISD::SRET_GLUE", SDTNone,
630b57cec5SDimitry Andric                             [SDNPHasChain, SDNPOptInGlue]>;
6406c3fb27SDimitry Andricdef riscv_mret_glue : SDNode<"RISCVISD::MRET_GLUE", SDTNone,
650b57cec5SDimitry Andric                             [SDNPHasChain, SDNPOptInGlue]>;
66e8d8bef9SDimitry Andricdef riscv_selectcc  : SDNode<"RISCVISD::SELECT_CC", SDT_RISCVSelectCC>;
67fe6060f1SDimitry Andricdef riscv_brcc      : SDNode<"RISCVISD::BR_CC", SDT_RISCVBrCC,
68fe6060f1SDimitry Andric                             [SDNPHasChain]>;
690b57cec5SDimitry Andricdef riscv_tail      : SDNode<"RISCVISD::TAIL", SDT_RISCVCall,
700b57cec5SDimitry Andric                             [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
710b57cec5SDimitry Andric                              SDNPVariadic]>;
72*0fca6ea1SDimitry Andricdef riscv_sw_guarded_brind : SDNode<"RISCVISD::SW_GUARDED_BRIND",
73*0fca6ea1SDimitry Andric                                    SDTBrind, [SDNPHasChain]>;
74fe6060f1SDimitry Andricdef riscv_sllw      : SDNode<"RISCVISD::SLLW", SDT_RISCVIntBinOpW>;
75fe6060f1SDimitry Andricdef riscv_sraw      : SDNode<"RISCVISD::SRAW", SDT_RISCVIntBinOpW>;
76fe6060f1SDimitry Andricdef riscv_srlw      : SDNode<"RISCVISD::SRLW", SDT_RISCVIntBinOpW>;
77fe6060f1SDimitry Andricdef riscv_read_csr  : SDNode<"RISCVISD::READ_CSR", SDT_RISCVReadCSR,
78fe6060f1SDimitry Andric                             [SDNPHasChain]>;
79fe6060f1SDimitry Andricdef riscv_write_csr : SDNode<"RISCVISD::WRITE_CSR", SDT_RISCVWriteCSR,
80fe6060f1SDimitry Andric                             [SDNPHasChain]>;
81fe6060f1SDimitry Andricdef riscv_swap_csr  : SDNode<"RISCVISD::SWAP_CSR", SDT_RISCVSwapCSR,
82fe6060f1SDimitry Andric                             [SDNPHasChain]>;
830b57cec5SDimitry Andric
84*0fca6ea1SDimitry Andricdef riscv_read_counter_wide : SDNode<"RISCVISD::READ_COUNTER_WIDE",
85*0fca6ea1SDimitry Andric                                     SDT_RISCVReadCounterWide,
86e8d8bef9SDimitry Andric                                     [SDNPHasChain, SDNPSideEffect]>;
87e8d8bef9SDimitry Andric
8881ad6265SDimitry Andricdef riscv_add_lo : SDNode<"RISCVISD::ADD_LO", SDTIntBinOp>;
8981ad6265SDimitry Andricdef riscv_hi : SDNode<"RISCVISD::HI", SDTIntUnaryOp>;
9081ad6265SDimitry Andricdef riscv_lla : SDNode<"RISCVISD::LLA", SDTIntUnaryOp>;
9181ad6265SDimitry Andricdef riscv_add_tprel : SDNode<"RISCVISD::ADD_TPREL",
9281ad6265SDimitry Andric                             SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>,
9381ad6265SDimitry Andric                                                  SDTCisSameAs<0, 2>,
9481ad6265SDimitry Andric                                                  SDTCisSameAs<0, 3>,
9581ad6265SDimitry Andric                                                  SDTCisInt<0>]>>;
9681ad6265SDimitry Andric
970b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
980b57cec5SDimitry Andric// Operand and SDNode transformation definitions.
990b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
1000b57cec5SDimitry Andric
1010b57cec5SDimitry Andricclass ImmXLenAsmOperand<string prefix, string suffix = ""> : AsmOperandClass {
1020b57cec5SDimitry Andric  let Name = prefix # "ImmXLen" # suffix;
1030b57cec5SDimitry Andric  let RenderMethod = "addImmOperands";
1040b57cec5SDimitry Andric  let DiagnosticType = !strconcat("Invalid", Name);
1050b57cec5SDimitry Andric}
1060b57cec5SDimitry Andric
1070b57cec5SDimitry Andricclass ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass {
1080b57cec5SDimitry Andric  let Name = prefix # "Imm" # width # suffix;
1090b57cec5SDimitry Andric  let RenderMethod = "addImmOperands";
1100b57cec5SDimitry Andric  let DiagnosticType = !strconcat("Invalid", Name);
1110b57cec5SDimitry Andric}
1120b57cec5SDimitry Andric
1138bcb0991SDimitry Andricdef ImmZeroAsmOperand : AsmOperandClass {
1148bcb0991SDimitry Andric  let Name = "ImmZero";
1158bcb0991SDimitry Andric  let RenderMethod = "addImmOperands";
1168bcb0991SDimitry Andric  let DiagnosticType = !strconcat("Invalid", Name);
1178bcb0991SDimitry Andric}
1188bcb0991SDimitry Andric
11981ad6265SDimitry Andric// A parse method for (${gpr}) or 0(${gpr}), where the 0 is be silently ignored.
12081ad6265SDimitry Andricdef ZeroOffsetMemOpOperand : AsmOperandClass {
12181ad6265SDimitry Andric  let Name = "ZeroOffsetMemOpOperand";
12281ad6265SDimitry Andric  let RenderMethod = "addRegOperands";
12381ad6265SDimitry Andric  let PredicateMethod = "isGPR";
12481ad6265SDimitry Andric  let ParserMethod = "parseZeroOffsetMemOp";
12581ad6265SDimitry Andric}
12681ad6265SDimitry Andric
127bdd1243dSDimitry Andricclass MemOperand<RegisterClass regClass> : RegisterOperand<regClass>{
128bdd1243dSDimitry Andric  let OperandType = "OPERAND_MEMORY";
129bdd1243dSDimitry Andric}
130bdd1243dSDimitry Andric
131bdd1243dSDimitry Andricdef GPRMemZeroOffset : MemOperand<GPR> {
13281ad6265SDimitry Andric  let ParserMatchClass = ZeroOffsetMemOpOperand;
13381ad6265SDimitry Andric  let PrintMethod = "printZeroOffsetMemOp";
13481ad6265SDimitry Andric}
13581ad6265SDimitry Andric
136bdd1243dSDimitry Andricdef GPRMem : MemOperand<GPR>;
137bdd1243dSDimitry Andric
138bdd1243dSDimitry Andricdef SPMem : MemOperand<SP>;
139bdd1243dSDimitry Andric
140bdd1243dSDimitry Andricdef GPRCMem : MemOperand<GPRC>;
141bdd1243dSDimitry Andric
1420b57cec5SDimitry Andricclass SImmAsmOperand<int width, string suffix = "">
1430b57cec5SDimitry Andric    : ImmAsmOperand<"S", width, suffix> {
1440b57cec5SDimitry Andric}
1450b57cec5SDimitry Andric
1460b57cec5SDimitry Andricclass UImmAsmOperand<int width, string suffix = "">
1470b57cec5SDimitry Andric    : ImmAsmOperand<"U", width, suffix> {
1480b57cec5SDimitry Andric}
1490b57cec5SDimitry Andric
1505f757f3fSDimitry Andricclass RISCVOp<ValueType vt = XLenVT> : Operand<vt> {
1515f757f3fSDimitry Andric  let OperandNamespace = "RISCVOp";
1525f757f3fSDimitry Andric}
1535f757f3fSDimitry Andric
1545f757f3fSDimitry Andricclass RISCVUImmOp<int bitsNum> : RISCVOp {
1555f757f3fSDimitry Andric  let ParserMatchClass = UImmAsmOperand<bitsNum>;
1565f757f3fSDimitry Andric  let DecoderMethod = "decodeUImmOperand<" # bitsNum # ">";
1575f757f3fSDimitry Andric  let OperandType = "OPERAND_UIMM" # bitsNum;
1585f757f3fSDimitry Andric}
1595f757f3fSDimitry Andric
1605f757f3fSDimitry Andricclass RISCVUImmLeafOp<int bitsNum> :
1615f757f3fSDimitry Andric  RISCVUImmOp<bitsNum>, ImmLeaf<XLenVT, "return isUInt<" # bitsNum # ">(Imm);">;
1625f757f3fSDimitry Andric
1635f757f3fSDimitry Andricclass RISCVSImmOp<int bitsNum> : RISCVOp {
1645f757f3fSDimitry Andric  let ParserMatchClass = SImmAsmOperand<bitsNum>;
1655f757f3fSDimitry Andric  let EncoderMethod = "getImmOpValue";
1665f757f3fSDimitry Andric  let DecoderMethod = "decodeSImmOperand<" # bitsNum # ">";
1675f757f3fSDimitry Andric  let OperandType = "OPERAND_SIMM" # bitsNum;
1685f757f3fSDimitry Andric}
1695f757f3fSDimitry Andric
1705f757f3fSDimitry Andricclass RISCVSImmLeafOp<int bitsNum> :
1715f757f3fSDimitry Andric  RISCVSImmOp<bitsNum>, ImmLeaf<XLenVT, "return isInt<" # bitsNum # ">(Imm);">;
1725f757f3fSDimitry Andric
1730b57cec5SDimitry Andricdef FenceArg : AsmOperandClass {
1740b57cec5SDimitry Andric  let Name = "FenceArg";
1750b57cec5SDimitry Andric  let RenderMethod = "addFenceArgOperands";
17606c3fb27SDimitry Andric  let ParserMethod = "parseFenceArg";
1770b57cec5SDimitry Andric}
1780b57cec5SDimitry Andric
1795f757f3fSDimitry Andricdef fencearg : RISCVOp {
1800b57cec5SDimitry Andric  let ParserMatchClass = FenceArg;
1810b57cec5SDimitry Andric  let PrintMethod = "printFenceArg";
1820b57cec5SDimitry Andric  let DecoderMethod = "decodeUImmOperand<4>";
1838bcb0991SDimitry Andric  let OperandType = "OPERAND_UIMM4";
1840b57cec5SDimitry Andric}
1850b57cec5SDimitry Andric
1860b57cec5SDimitry Andricdef UImmLog2XLenAsmOperand : AsmOperandClass {
1870b57cec5SDimitry Andric  let Name = "UImmLog2XLen";
1880b57cec5SDimitry Andric  let RenderMethod = "addImmOperands";
1890b57cec5SDimitry Andric  let DiagnosticType = "InvalidUImmLog2XLen";
1900b57cec5SDimitry Andric}
1910b57cec5SDimitry Andric
1925f757f3fSDimitry Andricdef uimmlog2xlen : RISCVOp, ImmLeaf<XLenVT, [{
1930b57cec5SDimitry Andric  if (Subtarget->is64Bit())
1940b57cec5SDimitry Andric    return isUInt<6>(Imm);
1950b57cec5SDimitry Andric  return isUInt<5>(Imm);
1960b57cec5SDimitry Andric}]> {
1970b57cec5SDimitry Andric  let ParserMatchClass = UImmLog2XLenAsmOperand;
1980b57cec5SDimitry Andric  // TODO: should ensure invalid shamt is rejected when decoding.
1990b57cec5SDimitry Andric  let DecoderMethod = "decodeUImmOperand<6>";
2000b57cec5SDimitry Andric  let MCOperandPredicate = [{
2010b57cec5SDimitry Andric    int64_t Imm;
2020b57cec5SDimitry Andric    if (!MCOp.evaluateAsConstantImm(Imm))
2030b57cec5SDimitry Andric      return false;
2040b57cec5SDimitry Andric    if (STI.getTargetTriple().isArch64Bit())
2050b57cec5SDimitry Andric      return isUInt<6>(Imm);
2060b57cec5SDimitry Andric    return isUInt<5>(Imm);
2070b57cec5SDimitry Andric  }];
2088bcb0991SDimitry Andric  let OperandType = "OPERAND_UIMMLOG2XLEN";
2090b57cec5SDimitry Andric}
2100b57cec5SDimitry Andric
2110eae32dcSDimitry Andricdef InsnDirectiveOpcode : AsmOperandClass {
2120eae32dcSDimitry Andric  let Name = "InsnDirectiveOpcode";
2130eae32dcSDimitry Andric  let ParserMethod = "parseInsnDirectiveOpcode";
2140eae32dcSDimitry Andric  let RenderMethod = "addImmOperands";
2150eae32dcSDimitry Andric  let PredicateMethod = "isImm";
2160eae32dcSDimitry Andric}
2170eae32dcSDimitry Andric
2185f757f3fSDimitry Andricdef uimm1 : RISCVUImmLeafOp<1>;
2195f757f3fSDimitry Andricdef uimm2 : RISCVUImmLeafOp<2> {
2205f757f3fSDimitry Andric  let MCOperandPredicate = [{
2215f757f3fSDimitry Andric    int64_t Imm;
2225f757f3fSDimitry Andric    if (!MCOp.evaluateAsConstantImm(Imm))
2235f757f3fSDimitry Andric      return false;
2245f757f3fSDimitry Andric    return isUInt<2>(Imm);
2255f757f3fSDimitry Andric  }];
22606c3fb27SDimitry Andric}
2275f757f3fSDimitry Andricdef uimm3 : RISCVUImmOp<3>;
2285f757f3fSDimitry Andricdef uimm4 : RISCVUImmOp<4>;
2295f757f3fSDimitry Andricdef uimm5 : RISCVUImmLeafOp<5>;
2305f757f3fSDimitry Andricdef uimm6 : RISCVUImmLeafOp<6>;
2315f757f3fSDimitry Andricdef uimm7_opcode : RISCVUImmOp<7> {
2320eae32dcSDimitry Andric  let ParserMatchClass = InsnDirectiveOpcode;
2330eae32dcSDimitry Andric}
2345f757f3fSDimitry Andricdef uimm7 : RISCVUImmOp<7>;
2355f757f3fSDimitry Andricdef uimm8 : RISCVUImmOp<8>;
236*0fca6ea1SDimitry Andricdef uimm16 : RISCVUImmOp<16>;
237*0fca6ea1SDimitry Andricdef uimm32 : RISCVUImmOp<32>;
2385f757f3fSDimitry Andricdef simm12 : RISCVSImmLeafOp<12> {
2390b57cec5SDimitry Andric  let MCOperandPredicate = [{
2400b57cec5SDimitry Andric    int64_t Imm;
2410b57cec5SDimitry Andric    if (MCOp.evaluateAsConstantImm(Imm))
2420b57cec5SDimitry Andric      return isInt<12>(Imm);
2430b57cec5SDimitry Andric    return MCOp.isBareSymbolRef();
2440b57cec5SDimitry Andric  }];
2450b57cec5SDimitry Andric}
2460b57cec5SDimitry Andric
247bdd1243dSDimitry Andric// A 12-bit signed immediate which cannot fit in 6-bit signed immediate,
248bdd1243dSDimitry Andric// but even negative value fit in 12-bit.
249bdd1243dSDimitry Andricdef simm12_no6 : ImmLeaf<XLenVT, [{
250bdd1243dSDimitry Andric  return isInt<12>(Imm) && !isInt<6>(Imm) && isInt<12>(-Imm);}]>;
251bdd1243dSDimitry Andric
2520b57cec5SDimitry Andric// A 13-bit signed immediate where the least significant bit is zero.
2530b57cec5SDimitry Andricdef simm13_lsb0 : Operand<OtherVT> {
2540b57cec5SDimitry Andric  let ParserMatchClass = SImmAsmOperand<13, "Lsb0">;
255e8d8bef9SDimitry Andric  let PrintMethod = "printBranchOperand";
2560b57cec5SDimitry Andric  let EncoderMethod = "getImmOpValueAsr1";
2570b57cec5SDimitry Andric  let DecoderMethod = "decodeSImmOperandAndLsl1<13>";
2580b57cec5SDimitry Andric  let MCOperandPredicate = [{
2590b57cec5SDimitry Andric    int64_t Imm;
2600b57cec5SDimitry Andric    if (MCOp.evaluateAsConstantImm(Imm))
2610b57cec5SDimitry Andric      return isShiftedInt<12, 1>(Imm);
2620b57cec5SDimitry Andric    return MCOp.isBareSymbolRef();
2630b57cec5SDimitry Andric  }];
264e8d8bef9SDimitry Andric  let OperandType = "OPERAND_PCREL";
2650b57cec5SDimitry Andric}
2660b57cec5SDimitry Andric
2675f757f3fSDimitry Andricclass UImm20Operand : RISCVOp {
2680b57cec5SDimitry Andric  let EncoderMethod = "getImmOpValue";
2690b57cec5SDimitry Andric  let DecoderMethod = "decodeUImmOperand<20>";
2705f757f3fSDimitry Andric  let OperandType = "OPERAND_UIMM20";
2715f757f3fSDimitry Andric}
2725f757f3fSDimitry Andric
2735f757f3fSDimitry Andricclass UImm20OperandMaybeSym : UImm20Operand {
2740b57cec5SDimitry Andric  let MCOperandPredicate = [{
2750b57cec5SDimitry Andric    int64_t Imm;
2760b57cec5SDimitry Andric    if (MCOp.evaluateAsConstantImm(Imm))
2770b57cec5SDimitry Andric      return isUInt<20>(Imm);
2780b57cec5SDimitry Andric    return MCOp.isBareSymbolRef();
2790b57cec5SDimitry Andric  }];
2800b57cec5SDimitry Andric}
2810b57cec5SDimitry Andric
2825f757f3fSDimitry Andricdef uimm20_lui : UImm20OperandMaybeSym {
2830b57cec5SDimitry Andric  let ParserMatchClass = UImmAsmOperand<20, "LUI">;
2840b57cec5SDimitry Andric}
2855f757f3fSDimitry Andricdef uimm20_auipc : UImm20OperandMaybeSym {
2860b57cec5SDimitry Andric  let ParserMatchClass = UImmAsmOperand<20, "AUIPC">;
2870b57cec5SDimitry Andric}
2880b57cec5SDimitry Andric
2895f757f3fSDimitry Andricdef uimm20 : UImm20Operand {
2905f757f3fSDimitry Andric  let ParserMatchClass = UImmAsmOperand<20>;
2915f757f3fSDimitry Andric  let MCOperandPredicate = [{
2925f757f3fSDimitry Andric    int64_t Imm;
2935f757f3fSDimitry Andric    if (!MCOp.evaluateAsConstantImm(Imm))
2945f757f3fSDimitry Andric      return false;
2955f757f3fSDimitry Andric    return isUInt<20>(Imm);
2965f757f3fSDimitry Andric  }];
2975f757f3fSDimitry Andric}
2985f757f3fSDimitry Andric
2990b57cec5SDimitry Andricdef Simm21Lsb0JALAsmOperand : SImmAsmOperand<21, "Lsb0JAL"> {
3000b57cec5SDimitry Andric  let ParserMethod = "parseJALOffset";
3010b57cec5SDimitry Andric}
3020b57cec5SDimitry Andric
3030b57cec5SDimitry Andric// A 21-bit signed immediate where the least significant bit is zero.
3040b57cec5SDimitry Andricdef simm21_lsb0_jal : Operand<OtherVT> {
3050b57cec5SDimitry Andric  let ParserMatchClass = Simm21Lsb0JALAsmOperand;
306e8d8bef9SDimitry Andric  let PrintMethod = "printBranchOperand";
3070b57cec5SDimitry Andric  let EncoderMethod = "getImmOpValueAsr1";
3080b57cec5SDimitry Andric  let DecoderMethod = "decodeSImmOperandAndLsl1<21>";
3090b57cec5SDimitry Andric  let MCOperandPredicate = [{
3100b57cec5SDimitry Andric    int64_t Imm;
3110b57cec5SDimitry Andric    if (MCOp.evaluateAsConstantImm(Imm))
3120b57cec5SDimitry Andric      return isShiftedInt<20, 1>(Imm);
3130b57cec5SDimitry Andric    return MCOp.isBareSymbolRef();
3140b57cec5SDimitry Andric  }];
315e8d8bef9SDimitry Andric  let OperandType = "OPERAND_PCREL";
3160b57cec5SDimitry Andric}
3170b57cec5SDimitry Andric
3180b57cec5SDimitry Andricdef BareSymbol : AsmOperandClass {
3190b57cec5SDimitry Andric  let Name = "BareSymbol";
3200b57cec5SDimitry Andric  let RenderMethod = "addImmOperands";
3210b57cec5SDimitry Andric  let DiagnosticType = "InvalidBareSymbol";
3220b57cec5SDimitry Andric  let ParserMethod = "parseBareSymbol";
3230b57cec5SDimitry Andric}
3240b57cec5SDimitry Andric
3250b57cec5SDimitry Andric// A bare symbol.
3260b57cec5SDimitry Andricdef bare_symbol : Operand<XLenVT> {
3270b57cec5SDimitry Andric  let ParserMatchClass = BareSymbol;
3280b57cec5SDimitry Andric}
3290b57cec5SDimitry Andric
3300b57cec5SDimitry Andricdef CallSymbol : AsmOperandClass {
3310b57cec5SDimitry Andric  let Name = "CallSymbol";
3320b57cec5SDimitry Andric  let RenderMethod = "addImmOperands";
3330b57cec5SDimitry Andric  let DiagnosticType = "InvalidCallSymbol";
3340b57cec5SDimitry Andric  let ParserMethod = "parseCallSymbol";
3350b57cec5SDimitry Andric}
3360b57cec5SDimitry Andric
3370b57cec5SDimitry Andric// A bare symbol used in call/tail only.
3380b57cec5SDimitry Andricdef call_symbol : Operand<XLenVT> {
3390b57cec5SDimitry Andric  let ParserMatchClass = CallSymbol;
3400b57cec5SDimitry Andric}
3410b57cec5SDimitry Andric
3425ffd83dbSDimitry Andricdef PseudoJumpSymbol : AsmOperandClass {
3435ffd83dbSDimitry Andric  let Name = "PseudoJumpSymbol";
3445ffd83dbSDimitry Andric  let RenderMethod = "addImmOperands";
3455ffd83dbSDimitry Andric  let DiagnosticType = "InvalidPseudoJumpSymbol";
3465ffd83dbSDimitry Andric  let ParserMethod = "parsePseudoJumpSymbol";
3475ffd83dbSDimitry Andric}
3485ffd83dbSDimitry Andric
3495ffd83dbSDimitry Andric// A bare symbol used for pseudo jumps only.
3505ffd83dbSDimitry Andricdef pseudo_jump_symbol : Operand<XLenVT> {
3515ffd83dbSDimitry Andric  let ParserMatchClass = PseudoJumpSymbol;
3525ffd83dbSDimitry Andric}
3535ffd83dbSDimitry Andric
3540b57cec5SDimitry Andricdef TPRelAddSymbol : AsmOperandClass {
3550b57cec5SDimitry Andric  let Name = "TPRelAddSymbol";
3560b57cec5SDimitry Andric  let RenderMethod = "addImmOperands";
3570b57cec5SDimitry Andric  let DiagnosticType = "InvalidTPRelAddSymbol";
3580b57cec5SDimitry Andric  let ParserMethod = "parseOperandWithModifier";
3590b57cec5SDimitry Andric}
3600b57cec5SDimitry Andric
3610b57cec5SDimitry Andric// A bare symbol with the %tprel_add variant.
3620b57cec5SDimitry Andricdef tprel_add_symbol : Operand<XLenVT> {
3630b57cec5SDimitry Andric  let ParserMatchClass = TPRelAddSymbol;
3640b57cec5SDimitry Andric}
3650b57cec5SDimitry Andric
3660b57cec5SDimitry Andricdef CSRSystemRegister : AsmOperandClass {
3670b57cec5SDimitry Andric  let Name = "CSRSystemRegister";
3680b57cec5SDimitry Andric  let ParserMethod = "parseCSRSystemRegister";
3690b57cec5SDimitry Andric  let DiagnosticType = "InvalidCSRSystemRegister";
3700b57cec5SDimitry Andric}
3710b57cec5SDimitry Andric
372*0fca6ea1SDimitry Andricdef csr_sysreg : RISCVOp, TImmLeaf<XLenVT, "return isUInt<12>(Imm);"> {
3730b57cec5SDimitry Andric  let ParserMatchClass = CSRSystemRegister;
3740b57cec5SDimitry Andric  let PrintMethod = "printCSRSystemRegister";
3750b57cec5SDimitry Andric  let DecoderMethod = "decodeUImmOperand<12>";
3768bcb0991SDimitry Andric  let OperandType = "OPERAND_UIMM12";
3770b57cec5SDimitry Andric}
3780b57cec5SDimitry Andric
3790b57cec5SDimitry Andric// A parameterized register class alternative to i32imm/i64imm from Target.td.
3800b57cec5SDimitry Andricdef ixlenimm : Operand<XLenVT>;
3810b57cec5SDimitry Andric
3820b57cec5SDimitry Andricdef ixlenimm_li : Operand<XLenVT> {
3830b57cec5SDimitry Andric  let ParserMatchClass = ImmXLenAsmOperand<"", "LI">;
3840b57cec5SDimitry Andric}
3850b57cec5SDimitry Andric
38606c3fb27SDimitry Andric// Accepts subset of LI operands, used by LAImm and LLAImm
38706c3fb27SDimitry Andricdef ixlenimm_li_restricted : Operand<XLenVT> {
38806c3fb27SDimitry Andric  let ParserMatchClass = ImmXLenAsmOperand<"", "LI_Restricted">;
38906c3fb27SDimitry Andric}
390fe6060f1SDimitry Andric
39106c3fb27SDimitry Andric// Standalone (codegen-only) immleaf patterns.
3920b57cec5SDimitry Andric
393e8d8bef9SDimitry Andric// A 6-bit constant greater than 32.
394e8d8bef9SDimitry Andricdef uimm6gt32 : ImmLeaf<XLenVT, [{
395e8d8bef9SDimitry Andric  return isUInt<6>(Imm) && Imm > 32;
396e8d8bef9SDimitry Andric}]>;
397e8d8bef9SDimitry Andric
3980b57cec5SDimitry Andric// Addressing modes.
3990b57cec5SDimitry Andric// Necessary because a frameindex can't be matched directly in a pattern.
40081ad6265SDimitry Andricdef FrameAddrRegImm : ComplexPattern<iPTR, 2, "SelectFrameAddrRegImm",
40181ad6265SDimitry Andric                                     [frameindex, or, add]>;
40281ad6265SDimitry Andricdef AddrRegImm : ComplexPattern<iPTR, 2, "SelectAddrRegImm">;
4030b57cec5SDimitry Andric
4045ffd83dbSDimitry Andric// Return the negation of an immediate value.
4055ffd83dbSDimitry Andricdef NegImm : SDNodeXForm<imm, [{
4065ffd83dbSDimitry Andric  return CurDAG->getTargetConstant(-N->getSExtValue(), SDLoc(N),
4075ffd83dbSDimitry Andric                                   N->getValueType(0));
4085ffd83dbSDimitry Andric}]>;
4095ffd83dbSDimitry Andric
410e8d8bef9SDimitry Andric// Return an immediate value minus 32.
411e8d8bef9SDimitry Andricdef ImmSub32 : SDNodeXForm<imm, [{
412e8d8bef9SDimitry Andric  return CurDAG->getTargetConstant(N->getSExtValue() - 32, SDLoc(N),
413e8d8bef9SDimitry Andric                                   N->getValueType(0));
414e8d8bef9SDimitry Andric}]>;
415e8d8bef9SDimitry Andric
416e8d8bef9SDimitry Andric// Return an immediate subtracted from XLen.
417e8d8bef9SDimitry Andricdef ImmSubFromXLen : SDNodeXForm<imm, [{
418e8d8bef9SDimitry Andric  uint64_t XLen = Subtarget->getXLen();
419e8d8bef9SDimitry Andric  return CurDAG->getTargetConstant(XLen - N->getZExtValue(), SDLoc(N),
420e8d8bef9SDimitry Andric                                   N->getValueType(0));
421e8d8bef9SDimitry Andric}]>;
422e8d8bef9SDimitry Andric
423e8d8bef9SDimitry Andric// Return an immediate subtracted from 32.
424e8d8bef9SDimitry Andricdef ImmSubFrom32 : SDNodeXForm<imm, [{
425e8d8bef9SDimitry Andric  return CurDAG->getTargetConstant(32 - N->getZExtValue(), SDLoc(N),
426e8d8bef9SDimitry Andric                                   N->getValueType(0));
427e8d8bef9SDimitry Andric}]>;
428e8d8bef9SDimitry Andric
429fe6060f1SDimitry Andric// Check if (add r, imm) can be optimized to (ADDI (ADDI r, imm0), imm1),
43081ad6265SDimitry Andric// in which imm = imm0 + imm1 and both imm0 and imm1 are simm12. We make imm0
43181ad6265SDimitry Andric// as large as possible and imm1 as small as possible so that we might be able
43281ad6265SDimitry Andric// to use c.addi for the small immediate.
433fe6060f1SDimitry Andricdef AddiPair : PatLeaf<(imm), [{
434fe6060f1SDimitry Andric  if (!N->hasOneUse())
435fe6060f1SDimitry Andric    return false;
436fe6060f1SDimitry Andric  // The immediate operand must be in range [-4096,-2049] or [2048,4094].
437fe6060f1SDimitry Andric  int64_t Imm = N->getSExtValue();
438fe6060f1SDimitry Andric  return (-4096 <= Imm && Imm <= -2049) || (2048 <= Imm && Imm <= 4094);
439fe6060f1SDimitry Andric}]>;
440fe6060f1SDimitry Andric
44181ad6265SDimitry Andric// Return imm - (imm < 0 ? -2048 : 2047).
44281ad6265SDimitry Andricdef AddiPairImmSmall : SDNodeXForm<imm, [{
44381ad6265SDimitry Andric  int64_t Imm = N->getSExtValue();
44481ad6265SDimitry Andric  int64_t Adj = N->getSExtValue() < 0 ? -2048 : 2047;
44581ad6265SDimitry Andric  return CurDAG->getTargetConstant(Imm - Adj, SDLoc(N),
446fe6060f1SDimitry Andric                                   N->getValueType(0));
447fe6060f1SDimitry Andric}]>;
448fe6060f1SDimitry Andric
44981ad6265SDimitry Andric// Return -2048 if immediate is negative or 2047 if positive. These are the
45081ad6265SDimitry Andric// largest simm12 values.
45181ad6265SDimitry Andricdef AddiPairImmLarge : SDNodeXForm<imm, [{
45281ad6265SDimitry Andric  int64_t Imm = N->getSExtValue() < 0 ? -2048 : 2047;
45381ad6265SDimitry Andric  return CurDAG->getTargetConstant(Imm, SDLoc(N),
454fe6060f1SDimitry Andric                                   N->getValueType(0));
455fe6060f1SDimitry Andric}]>;
456fe6060f1SDimitry Andric
45781ad6265SDimitry Andricdef TrailingZeros : SDNodeXForm<imm, [{
45806c3fb27SDimitry Andric  return CurDAG->getTargetConstant(llvm::countr_zero(N->getZExtValue()),
45981ad6265SDimitry Andric                                   SDLoc(N), N->getValueType(0));
46081ad6265SDimitry Andric}]>;
46181ad6265SDimitry Andric
46204eeddc0SDimitry Andricdef XLenSubTrailingOnes : SDNodeXForm<imm, [{
46304eeddc0SDimitry Andric  uint64_t XLen = Subtarget->getXLen();
46406c3fb27SDimitry Andric  uint64_t TrailingOnes = llvm::countr_one(N->getZExtValue());
46504eeddc0SDimitry Andric  return CurDAG->getTargetConstant(XLen - TrailingOnes, SDLoc(N),
46604eeddc0SDimitry Andric                                   N->getValueType(0));
46704eeddc0SDimitry Andric}]>;
46804eeddc0SDimitry Andric
46904eeddc0SDimitry Andric// Checks if this mask is a non-empty sequence of ones starting at the
47081ad6265SDimitry Andric// most/least significant bit with the remainder zero and exceeds simm32/simm12.
47181ad6265SDimitry Andricdef LeadingOnesMask : PatLeaf<(imm), [{
47281ad6265SDimitry Andric  if (!N->hasOneUse())
47381ad6265SDimitry Andric    return false;
47481ad6265SDimitry Andric  return !isInt<32>(N->getSExtValue()) && isMask_64(~N->getSExtValue());
47581ad6265SDimitry Andric}], TrailingZeros>;
47681ad6265SDimitry Andric
47704eeddc0SDimitry Andricdef TrailingOnesMask : PatLeaf<(imm), [{
47804eeddc0SDimitry Andric  if (!N->hasOneUse())
47904eeddc0SDimitry Andric    return false;
48004eeddc0SDimitry Andric  return !isInt<12>(N->getSExtValue()) && isMask_64(N->getZExtValue());
48104eeddc0SDimitry Andric}], XLenSubTrailingOnes>;
48204eeddc0SDimitry Andric
483bdd1243dSDimitry Andric// Similar to LeadingOnesMask, but only consider leading ones in the lower 32
484bdd1243dSDimitry Andric// bits.
485bdd1243dSDimitry Andricdef LeadingOnesWMask : PatLeaf<(imm), [{
486bdd1243dSDimitry Andric  if (!N->hasOneUse())
487bdd1243dSDimitry Andric    return false;
488bdd1243dSDimitry Andric  // If the value is a uint32 but not an int32, it must have bit 31 set and
489bdd1243dSDimitry Andric  // bits 63:32 cleared. After that we're looking for a shifted mask but not
490bdd1243dSDimitry Andric  // an all ones mask.
491bdd1243dSDimitry Andric  int64_t Imm = N->getSExtValue();
492bdd1243dSDimitry Andric  return !isInt<32>(Imm) && isUInt<32>(Imm) && isShiftedMask_64(Imm) &&
493bdd1243dSDimitry Andric         Imm != UINT64_C(0xffffffff);
494bdd1243dSDimitry Andric}], TrailingZeros>;
495bdd1243dSDimitry Andric
4960b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
4970b57cec5SDimitry Andric// Instruction Formats
4980b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
4990b57cec5SDimitry Andric
5000b57cec5SDimitry Andricinclude "RISCVInstrFormats.td"
5010b57cec5SDimitry Andric
5020b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
5030b57cec5SDimitry Andric// Instruction Class Templates
5040b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
5050b57cec5SDimitry Andric
5060b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
5070b57cec5SDimitry Andricclass BranchCC_rri<bits<3> funct3, string opcodestr>
5080b57cec5SDimitry Andric    : RVInstB<funct3, OPC_BRANCH, (outs),
5090b57cec5SDimitry Andric              (ins GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12),
51013138422SDimitry Andric              opcodestr, "$rs1, $rs2, $imm12">,
5115ffd83dbSDimitry Andric      Sched<[WriteJmp, ReadJmp, ReadJmp]> {
5120b57cec5SDimitry Andric  let isBranch = 1;
5130b57cec5SDimitry Andric  let isTerminator = 1;
5140b57cec5SDimitry Andric}
5150b57cec5SDimitry Andric
51681ad6265SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
5170b57cec5SDimitry Andricclass Load_ri<bits<3> funct3, string opcodestr>
518bdd1243dSDimitry Andric    : RVInstI<funct3, OPC_LOAD, (outs GPR:$rd), (ins GPRMem:$rs1, simm12:$imm12),
5190b57cec5SDimitry Andric              opcodestr, "$rd, ${imm12}(${rs1})">;
5200b57cec5SDimitry Andric
52181ad6265SDimitry Andricclass HLoad_r<bits<7> funct7, bits<5> funct5, string opcodestr>
52281ad6265SDimitry Andric    : RVInstR<funct7, 0b100, OPC_SYSTEM, (outs GPR:$rd),
52381ad6265SDimitry Andric              (ins GPRMemZeroOffset:$rs1), opcodestr, "$rd, $rs1"> {
52481ad6265SDimitry Andric  let rs2 = funct5;
52581ad6265SDimitry Andric}
52681ad6265SDimitry Andric}
52781ad6265SDimitry Andric
5280b57cec5SDimitry Andric// Operands for stores are in the order srcreg, base, offset rather than
5290b57cec5SDimitry Andric// reflecting the order these fields are specified in the instruction
5300b57cec5SDimitry Andric// encoding.
53181ad6265SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
5320b57cec5SDimitry Andricclass Store_rri<bits<3> funct3, string opcodestr>
5330b57cec5SDimitry Andric    : RVInstS<funct3, OPC_STORE, (outs),
534bdd1243dSDimitry Andric              (ins GPR:$rs2, GPRMem:$rs1, simm12:$imm12),
5350b57cec5SDimitry Andric              opcodestr, "$rs2, ${imm12}(${rs1})">;
5360b57cec5SDimitry Andric
53781ad6265SDimitry Andricclass HStore_rr<bits<7> funct7, string opcodestr>
53881ad6265SDimitry Andric    : RVInstR<funct7, 0b100, OPC_SYSTEM, (outs),
53981ad6265SDimitry Andric              (ins GPR:$rs2, GPRMemZeroOffset:$rs1),
54081ad6265SDimitry Andric               opcodestr, "$rs2, $rs1"> {
54181ad6265SDimitry Andric  let rd = 0;
54281ad6265SDimitry Andric}
54381ad6265SDimitry Andric}
54481ad6265SDimitry Andric
5450b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
5460b57cec5SDimitry Andricclass ALU_ri<bits<3> funct3, string opcodestr>
5470b57cec5SDimitry Andric    : RVInstI<funct3, OPC_OP_IMM, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12),
54813138422SDimitry Andric              opcodestr, "$rd, $rs1, $imm12">,
54913138422SDimitry Andric      Sched<[WriteIALU, ReadIALU]>;
5500b57cec5SDimitry Andric
5510b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
552fe6060f1SDimitry Andricclass Shift_ri<bits<5> imm11_7, bits<3> funct3, string opcodestr>
553fe6060f1SDimitry Andric    : RVInstIShift<imm11_7, funct3, OPC_OP_IMM, (outs GPR:$rd),
5540b57cec5SDimitry Andric                   (ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr,
55513138422SDimitry Andric                   "$rd, $rs1, $shamt">,
556fe6060f1SDimitry Andric      Sched<[WriteShiftImm, ReadShiftImm]>;
5570b57cec5SDimitry Andric
5580b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
55981ad6265SDimitry Andricclass ALU_rr<bits<7> funct7, bits<3> funct3, string opcodestr,
56081ad6265SDimitry Andric             bit Commutable = 0>
5610b57cec5SDimitry Andric    : RVInstR<funct7, funct3, OPC_OP, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2),
56281ad6265SDimitry Andric              opcodestr, "$rd, $rs1, $rs2"> {
56381ad6265SDimitry Andric  let isCommutable = Commutable;
56481ad6265SDimitry Andric}
5650b57cec5SDimitry Andric
566e8d8bef9SDimitry Andriclet hasNoSchedulingInfo = 1,
567e8d8bef9SDimitry Andric    hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
5680b57cec5SDimitry Andricclass CSR_ir<bits<3> funct3, string opcodestr>
5690b57cec5SDimitry Andric    : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd), (ins csr_sysreg:$imm12, GPR:$rs1),
57013138422SDimitry Andric              opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR, ReadCSR]>;
5710b57cec5SDimitry Andric
572e8d8bef9SDimitry Andriclet hasNoSchedulingInfo = 1,
573e8d8bef9SDimitry Andric    hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
5740b57cec5SDimitry Andricclass CSR_ii<bits<3> funct3, string opcodestr>
5750b57cec5SDimitry Andric    : RVInstI<funct3, OPC_SYSTEM, (outs GPR:$rd),
5760b57cec5SDimitry Andric              (ins csr_sysreg:$imm12, uimm5:$rs1),
57713138422SDimitry Andric              opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR]>;
5780b57cec5SDimitry Andric
5790b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
580fe6060f1SDimitry Andricclass ShiftW_ri<bits<7> imm11_5, bits<3> funct3, string opcodestr>
581fe6060f1SDimitry Andric    : RVInstIShiftW<imm11_5, funct3, OPC_OP_IMM_32, (outs GPR:$rd),
5820b57cec5SDimitry Andric                    (ins GPR:$rs1, uimm5:$shamt), opcodestr,
58313138422SDimitry Andric                    "$rd, $rs1, $shamt">,
584fe6060f1SDimitry Andric      Sched<[WriteShiftImm32, ReadShiftImm32]>;
5850b57cec5SDimitry Andric
5860b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
58781ad6265SDimitry Andricclass ALUW_rr<bits<7> funct7, bits<3> funct3, string opcodestr,
58881ad6265SDimitry Andric              bit Commutable = 0>
5890b57cec5SDimitry Andric    : RVInstR<funct7, funct3, OPC_OP_32, (outs GPR:$rd),
59081ad6265SDimitry Andric              (ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2"> {
59181ad6265SDimitry Andric  let isCommutable = Commutable;
59281ad6265SDimitry Andric}
5930b57cec5SDimitry Andric
5940b57cec5SDimitry Andriclet hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
5950b57cec5SDimitry Andricclass Priv<string opcodestr, bits<7> funct7>
5960b57cec5SDimitry Andric    : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2),
5970b57cec5SDimitry Andric              opcodestr, "">;
5980b57cec5SDimitry Andric
59981ad6265SDimitry Andriclet hasSideEffects = 1, mayLoad = 0, mayStore = 0 in
60081ad6265SDimitry Andricclass Priv_rr<string opcodestr, bits<7> funct7>
60181ad6265SDimitry Andric    : RVInstR<funct7, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2),
60281ad6265SDimitry Andric              opcodestr, "$rs1, $rs2"> {
60381ad6265SDimitry Andric  let rd = 0;
60481ad6265SDimitry Andric}
60581ad6265SDimitry Andric
6060b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
6070b57cec5SDimitry Andric// Instructions
6080b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
6090b57cec5SDimitry Andric
6100b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in {
611bdd1243dSDimitry Andriclet isReMaterializable = 1, isAsCheapAsAMove = 1,
612bdd1243dSDimitry Andric    IsSignExtendingOpW = 1 in
6130b57cec5SDimitry Andricdef LUI : RVInstU<OPC_LUI, (outs GPR:$rd), (ins uimm20_lui:$imm20),
61413138422SDimitry Andric                  "lui", "$rd, $imm20">, Sched<[WriteIALU]>;
6150b57cec5SDimitry Andric
6160b57cec5SDimitry Andricdef AUIPC : RVInstU<OPC_AUIPC, (outs GPR:$rd), (ins uimm20_auipc:$imm20),
61713138422SDimitry Andric                    "auipc", "$rd, $imm20">, Sched<[WriteIALU]>;
6180b57cec5SDimitry Andric
6190b57cec5SDimitry Andricdef JAL : RVInstJ<OPC_JAL, (outs GPR:$rd), (ins simm21_lsb0_jal:$imm20),
62013138422SDimitry Andric                  "jal", "$rd, $imm20">, Sched<[WriteJal]>;
6210b57cec5SDimitry Andric
6220b57cec5SDimitry Andricdef JALR : RVInstI<0b000, OPC_JALR, (outs GPR:$rd),
6230b57cec5SDimitry Andric                   (ins GPR:$rs1, simm12:$imm12),
62413138422SDimitry Andric                   "jalr", "$rd, ${imm12}(${rs1})">,
62513138422SDimitry Andric           Sched<[WriteJalr, ReadJalr]>;
6260b57cec5SDimitry Andric} // hasSideEffects = 0, mayLoad = 0, mayStore = 0
6270b57cec5SDimitry Andric
6280b57cec5SDimitry Andricdef BEQ  : BranchCC_rri<0b000, "beq">;
6290b57cec5SDimitry Andricdef BNE  : BranchCC_rri<0b001, "bne">;
6300b57cec5SDimitry Andricdef BLT  : BranchCC_rri<0b100, "blt">;
6310b57cec5SDimitry Andricdef BGE  : BranchCC_rri<0b101, "bge">;
6320b57cec5SDimitry Andricdef BLTU : BranchCC_rri<0b110, "bltu">;
6330b57cec5SDimitry Andricdef BGEU : BranchCC_rri<0b111, "bgeu">;
6340b57cec5SDimitry Andric
635bdd1243dSDimitry Andriclet IsSignExtendingOpW = 1 in {
63613138422SDimitry Andricdef LB  : Load_ri<0b000, "lb">, Sched<[WriteLDB, ReadMemBase]>;
63713138422SDimitry Andricdef LH  : Load_ri<0b001, "lh">, Sched<[WriteLDH, ReadMemBase]>;
63813138422SDimitry Andricdef LW  : Load_ri<0b010, "lw">, Sched<[WriteLDW, ReadMemBase]>;
63913138422SDimitry Andricdef LBU : Load_ri<0b100, "lbu">, Sched<[WriteLDB, ReadMemBase]>;
64013138422SDimitry Andricdef LHU : Load_ri<0b101, "lhu">, Sched<[WriteLDH, ReadMemBase]>;
641bdd1243dSDimitry Andric}
6420b57cec5SDimitry Andric
64313138422SDimitry Andricdef SB : Store_rri<0b000, "sb">, Sched<[WriteSTB, ReadStoreData, ReadMemBase]>;
64413138422SDimitry Andricdef SH : Store_rri<0b001, "sh">, Sched<[WriteSTH, ReadStoreData, ReadMemBase]>;
64513138422SDimitry Andricdef SW : Store_rri<0b010, "sw">, Sched<[WriteSTW, ReadStoreData, ReadMemBase]>;
6460b57cec5SDimitry Andric
6470b57cec5SDimitry Andric// ADDI isn't always rematerializable, but isReMaterializable will be used as
6480b57cec5SDimitry Andric// a hint which is verified in isReallyTriviallyReMaterializable.
6490b57cec5SDimitry Andriclet isReMaterializable = 1, isAsCheapAsAMove = 1 in
6500b57cec5SDimitry Andricdef ADDI  : ALU_ri<0b000, "addi">;
6510b57cec5SDimitry Andric
652bdd1243dSDimitry Andriclet IsSignExtendingOpW = 1 in {
6530b57cec5SDimitry Andricdef SLTI  : ALU_ri<0b010, "slti">;
6540b57cec5SDimitry Andricdef SLTIU : ALU_ri<0b011, "sltiu">;
655bdd1243dSDimitry Andric}
6560b57cec5SDimitry Andric
6570b57cec5SDimitry Andriclet isReMaterializable = 1, isAsCheapAsAMove = 1 in {
6580b57cec5SDimitry Andricdef XORI  : ALU_ri<0b100, "xori">;
6590b57cec5SDimitry Andricdef ORI   : ALU_ri<0b110, "ori">;
6600b57cec5SDimitry Andric}
6610b57cec5SDimitry Andric
6620b57cec5SDimitry Andricdef ANDI  : ALU_ri<0b111, "andi">;
6630b57cec5SDimitry Andric
664fe6060f1SDimitry Andricdef SLLI : Shift_ri<0b00000, 0b001, "slli">;
665fe6060f1SDimitry Andricdef SRLI : Shift_ri<0b00000, 0b101, "srli">;
666fe6060f1SDimitry Andricdef SRAI : Shift_ri<0b01000, 0b101, "srai">;
6670b57cec5SDimitry Andric
66806c3fb27SDimitry Andricdef ADD  : ALU_rr<0b0000000, 0b000, "add", Commutable=1>,
66981ad6265SDimitry Andric           Sched<[WriteIALU, ReadIALU, ReadIALU]>;
67081ad6265SDimitry Andricdef SUB  : ALU_rr<0b0100000, 0b000, "sub">,
67181ad6265SDimitry Andric           Sched<[WriteIALU, ReadIALU, ReadIALU]>;
67281ad6265SDimitry Andricdef SLL  : ALU_rr<0b0000000, 0b001, "sll">,
67381ad6265SDimitry Andric           Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>;
674bdd1243dSDimitry Andriclet IsSignExtendingOpW = 1 in {
67581ad6265SDimitry Andricdef SLT  : ALU_rr<0b0000000, 0b010, "slt">,
67681ad6265SDimitry Andric           Sched<[WriteIALU, ReadIALU, ReadIALU]>;
67781ad6265SDimitry Andricdef SLTU : ALU_rr<0b0000000, 0b011, "sltu">,
67881ad6265SDimitry Andric           Sched<[WriteIALU, ReadIALU, ReadIALU]>;
679bdd1243dSDimitry Andric}
68006c3fb27SDimitry Andricdef XOR  : ALU_rr<0b0000000, 0b100, "xor", Commutable=1>,
68181ad6265SDimitry Andric           Sched<[WriteIALU, ReadIALU, ReadIALU]>;
68281ad6265SDimitry Andricdef SRL  : ALU_rr<0b0000000, 0b101, "srl">,
68381ad6265SDimitry Andric           Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>;
68481ad6265SDimitry Andricdef SRA  : ALU_rr<0b0100000, 0b101, "sra">,
68581ad6265SDimitry Andric           Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>;
68606c3fb27SDimitry Andricdef OR   : ALU_rr<0b0000000, 0b110, "or", Commutable=1>,
68781ad6265SDimitry Andric           Sched<[WriteIALU, ReadIALU, ReadIALU]>;
68806c3fb27SDimitry Andricdef AND  : ALU_rr<0b0000000, 0b111, "and", Commutable=1>,
68981ad6265SDimitry Andric           Sched<[WriteIALU, ReadIALU, ReadIALU]>;
6900b57cec5SDimitry Andric
6910b57cec5SDimitry Andriclet hasSideEffects = 1, mayLoad = 0, mayStore = 0 in {
6920b57cec5SDimitry Andricdef FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs),
6930b57cec5SDimitry Andric                    (ins fencearg:$pred, fencearg:$succ),
69413138422SDimitry Andric                    "fence", "$pred, $succ">, Sched<[]> {
6950b57cec5SDimitry Andric  bits<4> pred;
6960b57cec5SDimitry Andric  bits<4> succ;
6970b57cec5SDimitry Andric
6980b57cec5SDimitry Andric  let rs1 = 0;
6990b57cec5SDimitry Andric  let rd = 0;
7000b57cec5SDimitry Andric  let imm12 = {0b0000,pred,succ};
7010b57cec5SDimitry Andric}
7020b57cec5SDimitry Andric
70313138422SDimitry Andricdef FENCE_TSO : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins), "fence.tso", "">, Sched<[]> {
7040b57cec5SDimitry Andric  let rs1 = 0;
7050b57cec5SDimitry Andric  let rd = 0;
7060b57cec5SDimitry Andric  let imm12 = {0b1000,0b0011,0b0011};
7070b57cec5SDimitry Andric}
7080b57cec5SDimitry Andric
70913138422SDimitry Andricdef FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), "fence.i", "">, Sched<[]> {
7100b57cec5SDimitry Andric  let rs1 = 0;
7110b57cec5SDimitry Andric  let rd = 0;
7120b57cec5SDimitry Andric  let imm12 = 0;
7130b57cec5SDimitry Andric}
7140b57cec5SDimitry Andric
71513138422SDimitry Andricdef ECALL : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ecall", "">, Sched<[WriteJmp]> {
7160b57cec5SDimitry Andric  let rs1 = 0;
7170b57cec5SDimitry Andric  let rd = 0;
7180b57cec5SDimitry Andric  let imm12 = 0;
7190b57cec5SDimitry Andric}
7200b57cec5SDimitry Andric
72113138422SDimitry Andricdef EBREAK : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ebreak", "">,
72213138422SDimitry Andric             Sched<[]> {
7230b57cec5SDimitry Andric  let rs1 = 0;
7240b57cec5SDimitry Andric  let rd = 0;
7250b57cec5SDimitry Andric  let imm12 = 1;
7260b57cec5SDimitry Andric}
7270b57cec5SDimitry Andric
7280b57cec5SDimitry Andric// This is a de facto standard (as set by GNU binutils) 32-bit unimplemented
7290b57cec5SDimitry Andric// instruction (i.e., it should always trap, if your implementation has invalid
7300b57cec5SDimitry Andric// instruction traps).
73113138422SDimitry Andricdef UNIMP : RVInstI<0b001, OPC_SYSTEM, (outs), (ins), "unimp", "">,
73213138422SDimitry Andric            Sched<[]> {
7330b57cec5SDimitry Andric  let rs1 = 0;
7340b57cec5SDimitry Andric  let rd = 0;
7350b57cec5SDimitry Andric  let imm12 = 0b110000000000;
7360b57cec5SDimitry Andric}
737bdd1243dSDimitry Andric
7380b57cec5SDimitry Andric} // hasSideEffects = 1, mayLoad = 0, mayStore = 0
7390b57cec5SDimitry Andric
7400b57cec5SDimitry Andricdef CSRRW : CSR_ir<0b001, "csrrw">;
7410b57cec5SDimitry Andricdef CSRRS : CSR_ir<0b010, "csrrs">;
7420b57cec5SDimitry Andricdef CSRRC : CSR_ir<0b011, "csrrc">;
7430b57cec5SDimitry Andric
7440b57cec5SDimitry Andricdef CSRRWI : CSR_ii<0b101, "csrrwi">;
7450b57cec5SDimitry Andricdef CSRRSI : CSR_ii<0b110, "csrrsi">;
7460b57cec5SDimitry Andricdef CSRRCI : CSR_ii<0b111, "csrrci">;
7470b57cec5SDimitry Andric
7480b57cec5SDimitry Andric/// RV64I instructions
7490b57cec5SDimitry Andric
7500b57cec5SDimitry Andriclet Predicates = [IsRV64] in {
751bdd1243dSDimitry Andricdef LWU   : Load_ri<0b110, "lwu">, Sched<[WriteLDW, ReadMemBase]>;
75213138422SDimitry Andricdef LD    : Load_ri<0b011, "ld">, Sched<[WriteLDD, ReadMemBase]>;
75313138422SDimitry Andricdef SD    : Store_rri<0b011, "sd">, Sched<[WriteSTD, ReadStoreData, ReadMemBase]>;
7540b57cec5SDimitry Andric
755bdd1243dSDimitry Andriclet IsSignExtendingOpW = 1 in {
7560b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
7570b57cec5SDimitry Andricdef ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd),
7580b57cec5SDimitry Andric                    (ins GPR:$rs1, simm12:$imm12),
75913138422SDimitry Andric                    "addiw", "$rd, $rs1, $imm12">,
76013138422SDimitry Andric            Sched<[WriteIALU32, ReadIALU32]>;
7610b57cec5SDimitry Andric
762fe6060f1SDimitry Andricdef SLLIW : ShiftW_ri<0b0000000, 0b001, "slliw">;
763fe6060f1SDimitry Andricdef SRLIW : ShiftW_ri<0b0000000, 0b101, "srliw">;
764fe6060f1SDimitry Andricdef SRAIW : ShiftW_ri<0b0100000, 0b101, "sraiw">;
7650b57cec5SDimitry Andric
76606c3fb27SDimitry Andricdef ADDW  : ALUW_rr<0b0000000, 0b000, "addw", Commutable=1>,
76713138422SDimitry Andric            Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;
76813138422SDimitry Andricdef SUBW  : ALUW_rr<0b0100000, 0b000, "subw">,
76913138422SDimitry Andric            Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;
77013138422SDimitry Andricdef SLLW  : ALUW_rr<0b0000000, 0b001, "sllw">,
771fe6060f1SDimitry Andric            Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>;
77213138422SDimitry Andricdef SRLW  : ALUW_rr<0b0000000, 0b101, "srlw">,
773fe6060f1SDimitry Andric            Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>;
77413138422SDimitry Andricdef SRAW  : ALUW_rr<0b0100000, 0b101, "sraw">,
775fe6060f1SDimitry Andric            Sched<[WriteShiftReg32, ReadShiftReg32, ReadShiftReg32]>;
776bdd1243dSDimitry Andric} // IsSignExtendingOpW = 1
7770b57cec5SDimitry Andric} // Predicates = [IsRV64]
7780b57cec5SDimitry Andric
7790b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
7800b57cec5SDimitry Andric// Privileged instructions
7810b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
7820b57cec5SDimitry Andric
7830b57cec5SDimitry Andriclet isBarrier = 1, isReturn = 1, isTerminator = 1 in {
78413138422SDimitry Andricdef SRET : Priv<"sret", 0b0001000>, Sched<[]> {
7850b57cec5SDimitry Andric  let rd = 0;
7860b57cec5SDimitry Andric  let rs1 = 0;
7870b57cec5SDimitry Andric  let rs2 = 0b00010;
7880b57cec5SDimitry Andric}
7890b57cec5SDimitry Andric
79013138422SDimitry Andricdef MRET : Priv<"mret", 0b0011000>, Sched<[]> {
7910b57cec5SDimitry Andric  let rd = 0;
7920b57cec5SDimitry Andric  let rs1 = 0;
7930b57cec5SDimitry Andric  let rs2 = 0b00010;
7940b57cec5SDimitry Andric}
7950b57cec5SDimitry Andric} // isBarrier = 1, isReturn = 1, isTerminator = 1
7960b57cec5SDimitry Andric
79713138422SDimitry Andricdef WFI : Priv<"wfi", 0b0001000>, Sched<[]> {
7980b57cec5SDimitry Andric  let rd = 0;
7990b57cec5SDimitry Andric  let rs1 = 0;
8000b57cec5SDimitry Andric  let rs2 = 0b00101;
8010b57cec5SDimitry Andric}
8020b57cec5SDimitry Andric
803bdd1243dSDimitry Andriclet Predicates = [HasStdExtSvinval] in {
80481ad6265SDimitry Andricdef SFENCE_W_INVAL : Priv<"sfence.w.inval", 0b0001100>, Sched<[]> {
8050b57cec5SDimitry Andric  let rd = 0;
80681ad6265SDimitry Andric  let rs1 = 0;
80781ad6265SDimitry Andric  let rs2 = 0;
80881ad6265SDimitry Andric}
80981ad6265SDimitry Andric
81081ad6265SDimitry Andricdef SFENCE_INVAL_IR : Priv<"sfence.inval.ir", 0b0001100>, Sched<[]> {
81181ad6265SDimitry Andric  let rd = 0;
81281ad6265SDimitry Andric  let rs1 = 0;
81381ad6265SDimitry Andric  let rs2 = 0b00001;
81481ad6265SDimitry Andric}
81581ad6265SDimitry Andricdef SINVAL_VMA  : Priv_rr<"sinval.vma", 0b0001011>, Sched<[]>;
81681ad6265SDimitry Andricdef HINVAL_VVMA : Priv_rr<"hinval.vvma", 0b0010011>, Sched<[]>;
81781ad6265SDimitry Andricdef HINVAL_GVMA : Priv_rr<"hinval.gvma", 0b0110011>, Sched<[]>;
818bdd1243dSDimitry Andric} // Predicates = [HasStdExtSvinval]
819bdd1243dSDimitry Andric
820bdd1243dSDimitry Andricdef SFENCE_VMA  : Priv_rr<"sfence.vma", 0b0001001>, Sched<[]>;
821bdd1243dSDimitry Andric
822bdd1243dSDimitry Andriclet Predicates = [HasStdExtH] in {
823bdd1243dSDimitry Andricdef HFENCE_VVMA : Priv_rr<"hfence.vvma", 0b0010001>, Sched<[]>;
824bdd1243dSDimitry Andricdef HFENCE_GVMA : Priv_rr<"hfence.gvma", 0b0110001>, Sched<[]>;
82581ad6265SDimitry Andric
82681ad6265SDimitry Andricdef HLV_B   : HLoad_r<0b0110000, 0b00000, "hlv.b">, Sched<[]>;
82781ad6265SDimitry Andricdef HLV_BU  : HLoad_r<0b0110000, 0b00001, "hlv.bu">, Sched<[]>;
82881ad6265SDimitry Andricdef HLV_H   : HLoad_r<0b0110010, 0b00000, "hlv.h">, Sched<[]>;
82981ad6265SDimitry Andricdef HLV_HU  : HLoad_r<0b0110010, 0b00001, "hlv.hu">, Sched<[]>;
83081ad6265SDimitry Andricdef HLVX_HU : HLoad_r<0b0110010, 0b00011, "hlvx.hu">, Sched<[]>;
83181ad6265SDimitry Andricdef HLV_W   : HLoad_r<0b0110100, 0b00000, "hlv.w">, Sched<[]>;
83281ad6265SDimitry Andricdef HLVX_WU : HLoad_r<0b0110100, 0b00011, "hlvx.wu">, Sched<[]>;
83381ad6265SDimitry Andricdef HSV_B   : HStore_rr<0b0110001, "hsv.b">, Sched<[]>;
83481ad6265SDimitry Andricdef HSV_H   : HStore_rr<0b0110011, "hsv.h">, Sched<[]>;
83581ad6265SDimitry Andricdef HSV_W   : HStore_rr<0b0110101, "hsv.w">, Sched<[]>;
836bdd1243dSDimitry Andric}
837bdd1243dSDimitry Andriclet Predicates = [IsRV64, HasStdExtH] in {
83881ad6265SDimitry Andricdef HLV_WU  : HLoad_r<0b0110100, 0b00001, "hlv.wu">, Sched<[]>;
83981ad6265SDimitry Andricdef HLV_D   : HLoad_r<0b0110110, 0b00000, "hlv.d">, Sched<[]>;
84081ad6265SDimitry Andricdef HSV_D   : HStore_rr<0b0110111, "hsv.d">, Sched<[]>;
8410b57cec5SDimitry Andric}
8420b57cec5SDimitry Andric
8430b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
8445ffd83dbSDimitry Andric// Debug instructions
8455ffd83dbSDimitry Andric//===----------------------------------------------------------------------===//
8465ffd83dbSDimitry Andric
8475ffd83dbSDimitry Andriclet isBarrier = 1, isReturn = 1, isTerminator = 1 in {
8485ffd83dbSDimitry Andricdef DRET : Priv<"dret", 0b0111101>, Sched<[]> {
8495ffd83dbSDimitry Andric  let rd = 0;
8505ffd83dbSDimitry Andric  let rs1 = 0;
8515ffd83dbSDimitry Andric  let rs2 = 0b10010;
8525ffd83dbSDimitry Andric}
8535ffd83dbSDimitry Andric} // isBarrier = 1, isReturn = 1, isTerminator = 1
8545ffd83dbSDimitry Andric
8555ffd83dbSDimitry Andric//===----------------------------------------------------------------------===//
8560b57cec5SDimitry Andric// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
8570b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
8580b57cec5SDimitry Andric
8590b57cec5SDimitry Andricdef : InstAlias<"nop",           (ADDI      X0,      X0,       0)>;
8600b57cec5SDimitry Andric
8610b57cec5SDimitry Andric// Note that the size is 32 because up to 8 32-bit instructions are needed to
8620b57cec5SDimitry Andric// generate an arbitrary 64-bit immediate. However, the size does not really
8630b57cec5SDimitry Andric// matter since PseudoLI is currently only used in the AsmParser where it gets
8640b57cec5SDimitry Andric// expanded to real instructions immediately.
8650b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32,
8660b57cec5SDimitry Andric    isCodeGenOnly = 0, isAsmParserOnly = 1 in
8670b57cec5SDimitry Andricdef PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm_li:$imm), [],
8680b57cec5SDimitry Andric                      "li", "$rd, $imm">;
8690b57cec5SDimitry Andric
8700b57cec5SDimitry Andricdef PseudoLB  : PseudoLoad<"lb">;
8710b57cec5SDimitry Andricdef PseudoLBU : PseudoLoad<"lbu">;
8720b57cec5SDimitry Andricdef PseudoLH  : PseudoLoad<"lh">;
8730b57cec5SDimitry Andricdef PseudoLHU : PseudoLoad<"lhu">;
8740b57cec5SDimitry Andricdef PseudoLW  : PseudoLoad<"lw">;
8750b57cec5SDimitry Andric
8760b57cec5SDimitry Andricdef PseudoSB  : PseudoStore<"sb">;
8770b57cec5SDimitry Andricdef PseudoSH  : PseudoStore<"sh">;
8780b57cec5SDimitry Andricdef PseudoSW  : PseudoStore<"sw">;
8790b57cec5SDimitry Andric
8800b57cec5SDimitry Andriclet Predicates = [IsRV64] in {
8810b57cec5SDimitry Andricdef PseudoLWU : PseudoLoad<"lwu">;
8820b57cec5SDimitry Andricdef PseudoLD  : PseudoLoad<"ld">;
8830b57cec5SDimitry Andricdef PseudoSD  : PseudoStore<"sd">;
8840b57cec5SDimitry Andric} // Predicates = [IsRV64]
8850b57cec5SDimitry Andric
8864824e7fdSDimitry Andricdef : InstAlias<"li $rd, $imm",  (ADDI GPR:$rd, X0, simm12:$imm)>;
8870b57cec5SDimitry Andricdef : InstAlias<"mv $rd, $rs",   (ADDI GPR:$rd, GPR:$rs,       0)>;
8880b57cec5SDimitry Andricdef : InstAlias<"not $rd, $rs",  (XORI GPR:$rd, GPR:$rs,      -1)>;
8890b57cec5SDimitry Andricdef : InstAlias<"neg $rd, $rs",  (SUB  GPR:$rd,      X0, GPR:$rs)>;
8900b57cec5SDimitry Andric
8910b57cec5SDimitry Andriclet Predicates = [IsRV64] in {
8920b57cec5SDimitry Andricdef : InstAlias<"negw $rd, $rs",   (SUBW  GPR:$rd,      X0, GPR:$rs)>;
8930b57cec5SDimitry Andricdef : InstAlias<"sext.w $rd, $rs", (ADDIW GPR:$rd, GPR:$rs,       0)>;
8940b57cec5SDimitry Andric} // Predicates = [IsRV64]
8950b57cec5SDimitry Andric
8960b57cec5SDimitry Andricdef : InstAlias<"seqz $rd, $rs", (SLTIU GPR:$rd, GPR:$rs,       1)>;
8970b57cec5SDimitry Andricdef : InstAlias<"snez $rd, $rs", (SLTU  GPR:$rd,      X0, GPR:$rs)>;
8980b57cec5SDimitry Andricdef : InstAlias<"sltz $rd, $rs", (SLT   GPR:$rd, GPR:$rs,      X0)>;
8990b57cec5SDimitry Andricdef : InstAlias<"sgtz $rd, $rs", (SLT   GPR:$rd,      X0, GPR:$rs)>;
9000b57cec5SDimitry Andric
9010b57cec5SDimitry Andric// sgt/sgtu are recognised by the GNU assembler but the canonical slt/sltu
9020b57cec5SDimitry Andric// form will always be printed. Therefore, set a zero weight.
9030b57cec5SDimitry Andricdef : InstAlias<"sgt $rd, $rs, $rt", (SLT GPR:$rd, GPR:$rt, GPR:$rs), 0>;
9040b57cec5SDimitry Andricdef : InstAlias<"sgtu $rd, $rs, $rt", (SLTU GPR:$rd, GPR:$rt, GPR:$rs), 0>;
9050b57cec5SDimitry Andric
9060b57cec5SDimitry Andricdef : InstAlias<"beqz $rs, $offset",
9070b57cec5SDimitry Andric                (BEQ GPR:$rs,      X0, simm13_lsb0:$offset)>;
9080b57cec5SDimitry Andricdef : InstAlias<"bnez $rs, $offset",
9090b57cec5SDimitry Andric                (BNE GPR:$rs,      X0, simm13_lsb0:$offset)>;
9100b57cec5SDimitry Andricdef : InstAlias<"blez $rs, $offset",
9110b57cec5SDimitry Andric                (BGE      X0, GPR:$rs, simm13_lsb0:$offset)>;
9120b57cec5SDimitry Andricdef : InstAlias<"bgez $rs, $offset",
9130b57cec5SDimitry Andric                (BGE GPR:$rs,      X0, simm13_lsb0:$offset)>;
9140b57cec5SDimitry Andricdef : InstAlias<"bltz $rs, $offset",
9150b57cec5SDimitry Andric                (BLT GPR:$rs,      X0, simm13_lsb0:$offset)>;
9160b57cec5SDimitry Andricdef : InstAlias<"bgtz $rs, $offset",
9170b57cec5SDimitry Andric                (BLT      X0, GPR:$rs, simm13_lsb0:$offset)>;
9180b57cec5SDimitry Andric
9190b57cec5SDimitry Andric// Always output the canonical mnemonic for the pseudo branch instructions.
9200b57cec5SDimitry Andric// The GNU tools emit the canonical mnemonic for the branch pseudo instructions
9210b57cec5SDimitry Andric// as well (e.g. "bgt" will be recognised by the assembler but never printed by
9220b57cec5SDimitry Andric// objdump). Match this behaviour by setting a zero weight.
9230b57cec5SDimitry Andricdef : InstAlias<"bgt $rs, $rt, $offset",
9240b57cec5SDimitry Andric                (BLT  GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
9250b57cec5SDimitry Andricdef : InstAlias<"ble $rs, $rt, $offset",
9260b57cec5SDimitry Andric                (BGE  GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
9270b57cec5SDimitry Andricdef : InstAlias<"bgtu $rs, $rt, $offset",
9280b57cec5SDimitry Andric                (BLTU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
9290b57cec5SDimitry Andricdef : InstAlias<"bleu $rs, $rt, $offset",
9300b57cec5SDimitry Andric                (BGEU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
9310b57cec5SDimitry Andric
9320b57cec5SDimitry Andricdef : InstAlias<"j $offset",   (JAL X0, simm21_lsb0_jal:$offset)>;
9330b57cec5SDimitry Andricdef : InstAlias<"jal $offset", (JAL X1, simm21_lsb0_jal:$offset)>;
9340b57cec5SDimitry Andric
9350b57cec5SDimitry Andric// Non-zero offset aliases of "jalr" are the lowest weight, followed by the
9360b57cec5SDimitry Andric// two-register form, then the one-register forms and finally "ret".
9370b57cec5SDimitry Andricdef : InstAlias<"jr $rs",                (JALR      X0, GPR:$rs, 0), 3>;
9380b57cec5SDimitry Andricdef : InstAlias<"jr ${offset}(${rs})",   (JALR      X0, GPR:$rs, simm12:$offset)>;
9390b57cec5SDimitry Andricdef : InstAlias<"jalr $rs",              (JALR      X1, GPR:$rs, 0), 3>;
9400b57cec5SDimitry Andricdef : InstAlias<"jalr ${offset}(${rs})", (JALR      X1, GPR:$rs, simm12:$offset)>;
9410b57cec5SDimitry Andricdef : InstAlias<"jalr $rd, $rs",         (JALR GPR:$rd, GPR:$rs, 0), 2>;
9420b57cec5SDimitry Andricdef : InstAlias<"ret",                   (JALR      X0,      X1, 0), 4>;
9430b57cec5SDimitry Andric
9440b57cec5SDimitry Andric// Non-canonical forms for jump targets also accepted by the assembler.
9450b57cec5SDimitry Andricdef : InstAlias<"jr $rs, $offset",        (JALR      X0, GPR:$rs, simm12:$offset), 0>;
9460b57cec5SDimitry Andricdef : InstAlias<"jalr $rs, $offset",      (JALR      X1, GPR:$rs, simm12:$offset), 0>;
9470b57cec5SDimitry Andricdef : InstAlias<"jalr $rd, $rs, $offset", (JALR GPR:$rd, GPR:$rs, simm12:$offset), 0>;
948*0fca6ea1SDimitry Andricdef : InstAlias<"jr (${rs})",             (JALR      X0, GPR:$rs, 0), 0>;
949*0fca6ea1SDimitry Andricdef : InstAlias<"jalr (${rs})",           (JALR      X1, GPR:$rs, 0), 0>;
950*0fca6ea1SDimitry Andricdef : InstAlias<"jalr $rd, (${rs})",      (JALR GPR:$rd, GPR:$rs, 0), 0>;
9510b57cec5SDimitry Andric
9520b57cec5SDimitry Andricdef : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw
9530b57cec5SDimitry Andric
95481ad6265SDimitry Andriclet Predicates = [HasStdExtZihintpause] in
95581ad6265SDimitry Andricdef : InstAlias<"pause", (FENCE 0x1, 0x0)>; // 0x1 == w
95681ad6265SDimitry Andric
9570b57cec5SDimitry Andricdef : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, INSTRET.Encoding, X0)>;
9580b57cec5SDimitry Andricdef : InstAlias<"rdcycle $rd",   (CSRRS GPR:$rd, CYCLE.Encoding, X0)>;
9590b57cec5SDimitry Andricdef : InstAlias<"rdtime $rd",    (CSRRS GPR:$rd, TIME.Encoding, X0)>;
9600b57cec5SDimitry Andric
9610b57cec5SDimitry Andriclet Predicates = [IsRV32] in {
9620b57cec5SDimitry Andricdef : InstAlias<"rdinstreth $rd", (CSRRS GPR:$rd, INSTRETH.Encoding, X0)>;
9630b57cec5SDimitry Andricdef : InstAlias<"rdcycleh $rd",   (CSRRS GPR:$rd, CYCLEH.Encoding, X0)>;
9640b57cec5SDimitry Andricdef : InstAlias<"rdtimeh $rd",    (CSRRS GPR:$rd, TIMEH.Encoding, X0)>;
9650b57cec5SDimitry Andric} // Predicates = [IsRV32]
9660b57cec5SDimitry Andric
9670b57cec5SDimitry Andricdef : InstAlias<"csrr $rd, $csr", (CSRRS GPR:$rd, csr_sysreg:$csr,      X0)>;
9680b57cec5SDimitry Andricdef : InstAlias<"csrw $csr, $rs", (CSRRW      X0, csr_sysreg:$csr, GPR:$rs)>;
9690b57cec5SDimitry Andricdef : InstAlias<"csrs $csr, $rs", (CSRRS      X0, csr_sysreg:$csr, GPR:$rs)>;
9700b57cec5SDimitry Andricdef : InstAlias<"csrc $csr, $rs", (CSRRC      X0, csr_sysreg:$csr, GPR:$rs)>;
9710b57cec5SDimitry Andric
9720b57cec5SDimitry Andricdef : InstAlias<"csrwi $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>;
9730b57cec5SDimitry Andricdef : InstAlias<"csrsi $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>;
9740b57cec5SDimitry Andricdef : InstAlias<"csrci $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>;
9750b57cec5SDimitry Andric
9760b57cec5SDimitry Andriclet EmitPriority = 0 in {
9770b57cec5SDimitry Andricdef : InstAlias<"csrw $csr, $imm", (CSRRWI X0, csr_sysreg:$csr, uimm5:$imm)>;
9780b57cec5SDimitry Andricdef : InstAlias<"csrs $csr, $imm", (CSRRSI X0, csr_sysreg:$csr, uimm5:$imm)>;
9790b57cec5SDimitry Andricdef : InstAlias<"csrc $csr, $imm", (CSRRCI X0, csr_sysreg:$csr, uimm5:$imm)>;
9800b57cec5SDimitry Andric
9810b57cec5SDimitry Andricdef : InstAlias<"csrrw $rd, $csr, $imm", (CSRRWI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>;
9820b57cec5SDimitry Andricdef : InstAlias<"csrrs $rd, $csr, $imm", (CSRRSI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>;
9830b57cec5SDimitry Andricdef : InstAlias<"csrrc $rd, $csr, $imm", (CSRRCI GPR:$rd, csr_sysreg:$csr, uimm5:$imm)>;
9840b57cec5SDimitry Andric}
9850b57cec5SDimitry Andric
9860b57cec5SDimitry Andricdef : InstAlias<"sfence.vma",     (SFENCE_VMA      X0, X0)>;
9870b57cec5SDimitry Andricdef : InstAlias<"sfence.vma $rs", (SFENCE_VMA GPR:$rs, X0)>;
9880b57cec5SDimitry Andric
98981ad6265SDimitry Andricdef : InstAlias<"hfence.gvma",     (HFENCE_GVMA      X0, X0)>;
99081ad6265SDimitry Andricdef : InstAlias<"hfence.gvma $rs", (HFENCE_GVMA GPR:$rs, X0)>;
99181ad6265SDimitry Andric
99281ad6265SDimitry Andricdef : InstAlias<"hfence.vvma",     (HFENCE_VVMA      X0, X0)>;
99381ad6265SDimitry Andricdef : InstAlias<"hfence.vvma $rs", (HFENCE_VVMA GPR:$rs, X0)>;
99481ad6265SDimitry Andric
995bdd1243dSDimitry Andriclet Predicates = [HasStdExtZihintntl] in {
996bdd1243dSDimitry Andric  def : InstAlias<"ntl.p1",     (ADD   X0, X0, X2)>;
997bdd1243dSDimitry Andric  def : InstAlias<"ntl.pall",   (ADD   X0, X0, X3)>;
998bdd1243dSDimitry Andric  def : InstAlias<"ntl.s1",     (ADD   X0, X0, X4)>;
999bdd1243dSDimitry Andric  def : InstAlias<"ntl.all",    (ADD   X0, X0, X5)>;
1000bdd1243dSDimitry Andric} // Predicates = [HasStdExtZihintntl]
1001bdd1243dSDimitry Andric
10020b57cec5SDimitry Andriclet EmitPriority = 0 in {
10030b57cec5SDimitry Andricdef : InstAlias<"lb $rd, (${rs1})",
10040b57cec5SDimitry Andric                (LB  GPR:$rd, GPR:$rs1, 0)>;
10050b57cec5SDimitry Andricdef : InstAlias<"lh $rd, (${rs1})",
10060b57cec5SDimitry Andric                (LH  GPR:$rd, GPR:$rs1, 0)>;
10070b57cec5SDimitry Andricdef : InstAlias<"lw $rd, (${rs1})",
10080b57cec5SDimitry Andric                (LW  GPR:$rd, GPR:$rs1, 0)>;
10090b57cec5SDimitry Andricdef : InstAlias<"lbu $rd, (${rs1})",
10100b57cec5SDimitry Andric                (LBU  GPR:$rd, GPR:$rs1, 0)>;
10110b57cec5SDimitry Andricdef : InstAlias<"lhu $rd, (${rs1})",
10120b57cec5SDimitry Andric                (LHU  GPR:$rd, GPR:$rs1, 0)>;
10130b57cec5SDimitry Andric
10140b57cec5SDimitry Andricdef : InstAlias<"sb $rs2, (${rs1})",
10150b57cec5SDimitry Andric                (SB  GPR:$rs2, GPR:$rs1, 0)>;
10160b57cec5SDimitry Andricdef : InstAlias<"sh $rs2, (${rs1})",
10170b57cec5SDimitry Andric                (SH  GPR:$rs2, GPR:$rs1, 0)>;
10180b57cec5SDimitry Andricdef : InstAlias<"sw $rs2, (${rs1})",
10190b57cec5SDimitry Andric                (SW  GPR:$rs2, GPR:$rs1, 0)>;
10200b57cec5SDimitry Andric
10210b57cec5SDimitry Andricdef : InstAlias<"add $rd, $rs1, $imm12",
10220b57cec5SDimitry Andric                (ADDI  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
10230b57cec5SDimitry Andricdef : InstAlias<"and $rd, $rs1, $imm12",
10240b57cec5SDimitry Andric                (ANDI  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
10250b57cec5SDimitry Andricdef : InstAlias<"xor $rd, $rs1, $imm12",
10260b57cec5SDimitry Andric                (XORI  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
10270b57cec5SDimitry Andricdef : InstAlias<"or $rd, $rs1, $imm12",
10280b57cec5SDimitry Andric                (ORI  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
10290b57cec5SDimitry Andricdef : InstAlias<"sll $rd, $rs1, $shamt",
10300b57cec5SDimitry Andric                (SLLI  GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;
10310b57cec5SDimitry Andricdef : InstAlias<"srl $rd, $rs1, $shamt",
10320b57cec5SDimitry Andric                (SRLI  GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;
10330b57cec5SDimitry Andricdef : InstAlias<"sra $rd, $rs1, $shamt",
10340b57cec5SDimitry Andric                (SRAI  GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt)>;
10350b57cec5SDimitry Andriclet Predicates = [IsRV64] in {
10360b57cec5SDimitry Andricdef : InstAlias<"lwu $rd, (${rs1})",
10370b57cec5SDimitry Andric                (LWU  GPR:$rd, GPR:$rs1, 0)>;
10380b57cec5SDimitry Andricdef : InstAlias<"ld $rd, (${rs1})",
10390b57cec5SDimitry Andric                (LD  GPR:$rd, GPR:$rs1, 0)>;
10400b57cec5SDimitry Andricdef : InstAlias<"sd $rs2, (${rs1})",
10410b57cec5SDimitry Andric                (SD  GPR:$rs2, GPR:$rs1, 0)>;
10420b57cec5SDimitry Andric
10430b57cec5SDimitry Andricdef : InstAlias<"addw $rd, $rs1, $imm12",
10440b57cec5SDimitry Andric                (ADDIW  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
10450b57cec5SDimitry Andricdef : InstAlias<"sllw $rd, $rs1, $shamt",
10460b57cec5SDimitry Andric                (SLLIW  GPR:$rd, GPR:$rs1, uimm5:$shamt)>;
10470b57cec5SDimitry Andricdef : InstAlias<"srlw $rd, $rs1, $shamt",
10480b57cec5SDimitry Andric                (SRLIW  GPR:$rd, GPR:$rs1, uimm5:$shamt)>;
10490b57cec5SDimitry Andricdef : InstAlias<"sraw $rd, $rs1, $shamt",
10500b57cec5SDimitry Andric                (SRAIW  GPR:$rd, GPR:$rs1, uimm5:$shamt)>;
10510b57cec5SDimitry Andric} // Predicates = [IsRV64]
10520b57cec5SDimitry Andricdef : InstAlias<"slt $rd, $rs1, $imm12",
10530b57cec5SDimitry Andric                (SLTI  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
10540b57cec5SDimitry Andricdef : InstAlias<"sltu $rd, $rs1, $imm12",
10550b57cec5SDimitry Andric                (SLTIU  GPR:$rd, GPR:$rs1, simm12:$imm12)>;
10560b57cec5SDimitry Andric}
10570b57cec5SDimitry Andric
10580b57cec5SDimitry Andricdef : MnemonicAlias<"move", "mv">;
10590b57cec5SDimitry Andric
10600b57cec5SDimitry Andric// The SCALL and SBREAK instructions wererenamed to ECALL and EBREAK in
10610b57cec5SDimitry Andric// version 2.1 of the user-level ISA. Like the GNU toolchain, we still accept
10620b57cec5SDimitry Andric// the old name for backwards compatibility.
10630b57cec5SDimitry Andricdef : MnemonicAlias<"scall", "ecall">;
10640b57cec5SDimitry Andricdef : MnemonicAlias<"sbreak", "ebreak">;
10650b57cec5SDimitry Andric
1066e8d8bef9SDimitry Andric// This alias was added to the spec in December 2020. Don't print it by default
1067e8d8bef9SDimitry Andric// to allow assembly we print to be compatible with versions of GNU assembler
1068e8d8bef9SDimitry Andric// that don't support this alias.
1069e8d8bef9SDimitry Andricdef : InstAlias<"zext.b $rd, $rs", (ANDI GPR:$rd, GPR:$rs, 0xFF), 0>;
1070e8d8bef9SDimitry Andric
10715f757f3fSDimitry Andriclet Predicates = [HasStdExtZicfilp] in {
10725f757f3fSDimitry Andricdef : InstAlias<"lpad $imm20", (AUIPC X0, uimm20:$imm20)>;
10735f757f3fSDimitry Andric}
10745f757f3fSDimitry Andric
10750b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
1076349cc55cSDimitry Andric// .insn directive instructions
1077349cc55cSDimitry Andric//===----------------------------------------------------------------------===//
1078349cc55cSDimitry Andric
107906c3fb27SDimitry Andricdef AnyRegOperand : AsmOperandClass {
108006c3fb27SDimitry Andric  let Name = "AnyRegOperand";
108106c3fb27SDimitry Andric  let RenderMethod = "addRegOperands";
108206c3fb27SDimitry Andric  let PredicateMethod = "isAnyReg";
108306c3fb27SDimitry Andric}
108406c3fb27SDimitry Andric
108506c3fb27SDimitry Andricdef AnyReg : Operand<XLenVT> {
108606c3fb27SDimitry Andric  let OperandType = "OPERAND_REGISTER";
108706c3fb27SDimitry Andric  let ParserMatchClass = AnyRegOperand;
108806c3fb27SDimitry Andric}
108906c3fb27SDimitry Andric
1090349cc55cSDimitry Andric// isCodeGenOnly = 1 to hide them from the tablegened assembly parser.
1091349cc55cSDimitry Andriclet isCodeGenOnly = 1, hasSideEffects = 1, mayLoad = 1, mayStore = 1,
1092349cc55cSDimitry Andric    hasNoSchedulingInfo = 1 in {
10930eae32dcSDimitry Andricdef InsnR : DirectiveInsnR<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$funct3,
1094349cc55cSDimitry Andric                                                   uimm7:$funct7, AnyReg:$rs1,
1095349cc55cSDimitry Andric                                                   AnyReg:$rs2),
1096349cc55cSDimitry Andric                           "$opcode, $funct3, $funct7, $rd, $rs1, $rs2">;
10970eae32dcSDimitry Andricdef InsnR4 : DirectiveInsnR4<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode,
1098349cc55cSDimitry Andric                                                     uimm3:$funct3,
1099349cc55cSDimitry Andric                                                     uimm2:$funct2,
1100349cc55cSDimitry Andric                                                     AnyReg:$rs1, AnyReg:$rs2,
1101349cc55cSDimitry Andric                                                     AnyReg:$rs3),
1102349cc55cSDimitry Andric                            "$opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3">;
11030eae32dcSDimitry Andricdef InsnI : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode, uimm3:$funct3,
1104349cc55cSDimitry Andric                                                   AnyReg:$rs1, simm12:$imm12),
1105349cc55cSDimitry Andric                           "$opcode, $funct3, $rd, $rs1, $imm12">;
11060eae32dcSDimitry Andricdef InsnI_Mem : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode,
1107349cc55cSDimitry Andric                                                       uimm3:$funct3,
1108349cc55cSDimitry Andric                                                       AnyReg:$rs1,
1109349cc55cSDimitry Andric                                                       simm12:$imm12),
1110349cc55cSDimitry Andric                               "$opcode, $funct3, $rd, ${imm12}(${rs1})">;
11110eae32dcSDimitry Andricdef InsnB : DirectiveInsnB<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3,
1112349cc55cSDimitry Andric                                        AnyReg:$rs1, AnyReg:$rs2,
1113349cc55cSDimitry Andric                                        simm13_lsb0:$imm12),
1114349cc55cSDimitry Andric                           "$opcode, $funct3, $rs1, $rs2, $imm12">;
11150eae32dcSDimitry Andricdef InsnU : DirectiveInsnU<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode,
1116349cc55cSDimitry Andric                                                   uimm20_lui:$imm20),
1117349cc55cSDimitry Andric                           "$opcode, $rd, $imm20">;
11180eae32dcSDimitry Andricdef InsnJ : DirectiveInsnJ<(outs AnyReg:$rd), (ins uimm7_opcode:$opcode,
1119349cc55cSDimitry Andric                                                   simm21_lsb0_jal:$imm20),
1120349cc55cSDimitry Andric                           "$opcode, $rd, $imm20">;
11210eae32dcSDimitry Andricdef InsnS : DirectiveInsnS<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3,
1122349cc55cSDimitry Andric                                        AnyReg:$rs2, AnyReg:$rs1,
1123349cc55cSDimitry Andric                                        simm12:$imm12),
1124349cc55cSDimitry Andric                           "$opcode, $funct3, $rs2, ${imm12}(${rs1})">;
1125*0fca6ea1SDimitry Andricdef Insn32 : RVInst<(outs), (ins uimm32:$value), "", "", [], InstFormatOther> {
1126*0fca6ea1SDimitry Andric  bits<32> value;
1127*0fca6ea1SDimitry Andric
1128*0fca6ea1SDimitry Andric  let Inst{31-0} = value;
1129*0fca6ea1SDimitry Andric  let AsmString = ".insn 0x4, $value";
1130*0fca6ea1SDimitry Andric}
1131349cc55cSDimitry Andric}
1132349cc55cSDimitry Andric
1133349cc55cSDimitry Andric// Use InstAliases to match these so that we can combine the insn and format
1134349cc55cSDimitry Andric// into a mnemonic to use as the key for the tablegened asm matcher table. The
1135349cc55cSDimitry Andric// parser will take care of creating these fake mnemonics and will only do it
1136349cc55cSDimitry Andric// for known formats.
1137349cc55cSDimitry Andriclet EmitPriority = 0 in {
1138349cc55cSDimitry Andricdef : InstAlias<".insn_r $opcode, $funct3, $funct7, $rd, $rs1, $rs2",
11390eae32dcSDimitry Andric                (InsnR AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm7:$funct7,
1140349cc55cSDimitry Andric                       AnyReg:$rs1, AnyReg:$rs2)>;
1141349cc55cSDimitry Andric// Accept 4 register form of ".insn r" as alias for ".insn r4".
1142349cc55cSDimitry Andricdef : InstAlias<".insn_r $opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3",
11430eae32dcSDimitry Andric                (InsnR4 AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm2:$funct2,
1144349cc55cSDimitry Andric                        AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>;
1145349cc55cSDimitry Andricdef : InstAlias<".insn_r4 $opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3",
11460eae32dcSDimitry Andric                (InsnR4 AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, uimm2:$funct2,
1147349cc55cSDimitry Andric                        AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>;
1148349cc55cSDimitry Andricdef : InstAlias<".insn_i $opcode, $funct3, $rd, $rs1, $imm12",
11490eae32dcSDimitry Andric                (InsnI AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1,
1150349cc55cSDimitry Andric                       simm12:$imm12)>;
1151349cc55cSDimitry Andricdef : InstAlias<".insn_i $opcode, $funct3, $rd, ${imm12}(${rs1})",
11520eae32dcSDimitry Andric                (InsnI_Mem AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3,
1153349cc55cSDimitry Andric                           AnyReg:$rs1, simm12:$imm12)>;
1154*0fca6ea1SDimitry Andricdef : InstAlias<".insn_i $opcode, $funct3, $rd, (${rs1})",
1155*0fca6ea1SDimitry Andric                (InsnI_Mem AnyReg:$rd, uimm7_opcode:$opcode, uimm3:$funct3,
1156*0fca6ea1SDimitry Andric                           AnyReg:$rs1, 0)>;
1157349cc55cSDimitry Andricdef : InstAlias<".insn_b $opcode, $funct3, $rs1, $rs2, $imm12",
11580eae32dcSDimitry Andric                (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1,
1159349cc55cSDimitry Andric                       AnyReg:$rs2, simm13_lsb0:$imm12)>;
1160349cc55cSDimitry Andric// Accept sb as an alias for b.
1161349cc55cSDimitry Andricdef : InstAlias<".insn_sb $opcode, $funct3, $rs1, $rs2, $imm12",
11620eae32dcSDimitry Andric                (InsnB uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs1,
1163349cc55cSDimitry Andric                       AnyReg:$rs2, simm13_lsb0:$imm12)>;
1164349cc55cSDimitry Andricdef : InstAlias<".insn_u $opcode, $rd, $imm20",
11650eae32dcSDimitry Andric                (InsnU AnyReg:$rd, uimm7_opcode:$opcode, uimm20_lui:$imm20)>;
1166349cc55cSDimitry Andricdef : InstAlias<".insn_j $opcode, $rd, $imm20",
11670eae32dcSDimitry Andric                (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>;
1168349cc55cSDimitry Andric// Accept uj as an alias for j.
1169349cc55cSDimitry Andricdef : InstAlias<".insn_uj $opcode, $rd, $imm20",
11700eae32dcSDimitry Andric                (InsnJ AnyReg:$rd, uimm7_opcode:$opcode, simm21_lsb0_jal:$imm20)>;
1171349cc55cSDimitry Andricdef : InstAlias<".insn_s $opcode, $funct3, $rs2, ${imm12}(${rs1})",
11720eae32dcSDimitry Andric                (InsnS uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs2,
1173349cc55cSDimitry Andric                       AnyReg:$rs1, simm12:$imm12)>;
1174*0fca6ea1SDimitry Andricdef : InstAlias<".insn_s $opcode, $funct3, $rs2, (${rs1})",
1175*0fca6ea1SDimitry Andric                (InsnS uimm7_opcode:$opcode, uimm3:$funct3, AnyReg:$rs2,
1176*0fca6ea1SDimitry Andric                       AnyReg:$rs1, 0)>;
1177349cc55cSDimitry Andric}
1178349cc55cSDimitry Andric
1179349cc55cSDimitry Andric//===----------------------------------------------------------------------===//
11800b57cec5SDimitry Andric// Pseudo-instructions and codegen patterns
11810b57cec5SDimitry Andric//
11820b57cec5SDimitry Andric// Naming convention: For 'generic' pattern classes, we use the naming
11830b57cec5SDimitry Andric// convention PatTy1Ty2. For pattern classes which offer a more complex
11845ffd83dbSDimitry Andric// expansion, prefix the class name, e.g. BccPat.
11850b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
11860b57cec5SDimitry Andric
11870b57cec5SDimitry Andric/// Generic pattern classes
11880b57cec5SDimitry Andric
118906c3fb27SDimitry Andricclass PatGpr<SDPatternOperator OpNode, RVInst Inst, ValueType vt = XLenVT>
119006c3fb27SDimitry Andric    : Pat<(vt (OpNode (vt GPR:$rs1))), (Inst GPR:$rs1)>;
11915f757f3fSDimitry Andricclass PatGprGpr<SDPatternOperator OpNode, RVInst Inst, ValueType vt1 = XLenVT,
11925f757f3fSDimitry Andric                ValueType vt2 = XLenVT>
11935f757f3fSDimitry Andric    : Pat<(vt1 (OpNode (vt1 GPR:$rs1), (vt2 GPR:$rs2))), (Inst GPR:$rs1, GPR:$rs2)>;
1194fe6060f1SDimitry Andric
11955f757f3fSDimitry Andricclass PatGprImm<SDPatternOperator OpNode, RVInst Inst, ImmLeaf ImmType,
11965f757f3fSDimitry Andric                ValueType vt = XLenVT>
11975f757f3fSDimitry Andric    : Pat<(vt (OpNode (vt GPR:$rs1), ImmType:$imm)),
1198fe6060f1SDimitry Andric          (Inst GPR:$rs1, ImmType:$imm)>;
11990b57cec5SDimitry Andricclass PatGprSimm12<SDPatternOperator OpNode, RVInstI Inst>
1200fe6060f1SDimitry Andric    : PatGprImm<OpNode, Inst, simm12>;
12010b57cec5SDimitry Andricclass PatGprUimmLog2XLen<SDPatternOperator OpNode, RVInstIShift Inst>
1202fe6060f1SDimitry Andric    : PatGprImm<OpNode, Inst, uimmlog2xlen>;
12030b57cec5SDimitry Andric
12040b57cec5SDimitry Andric/// Predicates
12050b57cec5SDimitry Andric
12060b57cec5SDimitry Andricdef assertsexti32 : PatFrag<(ops node:$src), (assertsext node:$src), [{
1207e8d8bef9SDimitry Andric  return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32);
12080b57cec5SDimitry Andric}]>;
120906c3fb27SDimitry Andricdef sexti16 : ComplexPattern<XLenVT, 1, "selectSExtBits<16>">;
1210*0fca6ea1SDimitry Andricdef sexti16i32 : ComplexPattern<i32, 1, "selectSExtBits<16>">;
121106c3fb27SDimitry Andricdef sexti32 : ComplexPattern<i64, 1, "selectSExtBits<32>">;
12120b57cec5SDimitry Andricdef assertzexti32 : PatFrag<(ops node:$src), (assertzext node:$src), [{
1213e8d8bef9SDimitry Andric  return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLE(MVT::i32);
12140b57cec5SDimitry Andric}]>;
1215bdd1243dSDimitry Andricdef zexti32 : ComplexPattern<i64, 1, "selectZExtBits<32>">;
1216bdd1243dSDimitry Andricdef zexti16 : ComplexPattern<XLenVT, 1, "selectZExtBits<16>">;
12175f757f3fSDimitry Andricdef zexti16i32 : ComplexPattern<i32, 1, "selectZExtBits<16>">;
1218bdd1243dSDimitry Andricdef zexti8 : ComplexPattern<XLenVT, 1, "selectZExtBits<8>">;
12195f757f3fSDimitry Andricdef zexti8i32 : ComplexPattern<i32, 1, "selectZExtBits<8>">;
12200b57cec5SDimitry Andric
122106c3fb27SDimitry Andricdef ext : PatFrags<(ops node:$A), [(sext node:$A), (zext node:$A)]>;
122206c3fb27SDimitry Andric
122381ad6265SDimitry Andricclass binop_oneuse<SDPatternOperator operator>
122481ad6265SDimitry Andric    : PatFrag<(ops node:$A, node:$B),
122581ad6265SDimitry Andric              (operator node:$A, node:$B), [{
1226fe6060f1SDimitry Andric  return N->hasOneUse();
1227e8d8bef9SDimitry Andric}]>;
1228e8d8bef9SDimitry Andric
1229bdd1243dSDimitry Andricdef and_oneuse : binop_oneuse<and>;
123081ad6265SDimitry Andricdef mul_oneuse : binop_oneuse<mul>;
1231e8d8bef9SDimitry Andric
1232349cc55cSDimitry Andricdef mul_const_oneuse : PatFrag<(ops node:$A, node:$B),
1233349cc55cSDimitry Andric                               (mul node:$A, node:$B), [{
1234349cc55cSDimitry Andric  if (auto *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1)))
123506c3fb27SDimitry Andric    return N1C->hasOneUse();
1236349cc55cSDimitry Andric  return false;
1237349cc55cSDimitry Andric}]>;
1238349cc55cSDimitry Andric
123981ad6265SDimitry Andricclass unop_oneuse<SDPatternOperator operator>
124081ad6265SDimitry Andric    : PatFrag<(ops node:$A),
124181ad6265SDimitry Andric              (operator node:$A), [{
124204eeddc0SDimitry Andric  return N->hasOneUse();
124304eeddc0SDimitry Andric}]>;
124404eeddc0SDimitry Andric
124581ad6265SDimitry Andricdef sext_oneuse   : unop_oneuse<sext>;
124681ad6265SDimitry Andricdef zext_oneuse   : unop_oneuse<zext>;
124781ad6265SDimitry Andricdef anyext_oneuse : unop_oneuse<anyext>;
124806c3fb27SDimitry Andricdef ext_oneuse    : unop_oneuse<ext>;
124981ad6265SDimitry Andricdef fpext_oneuse  : unop_oneuse<any_fpextend>;
125004eeddc0SDimitry Andric
12515f757f3fSDimitry Andricdef 33signbits_node : PatLeaf<(i64 GPR:$src), [{
12525f757f3fSDimitry Andric  return CurDAG->ComputeNumSignBits(SDValue(N, 0)) > 32;
12535f757f3fSDimitry Andric}]>;
12545f757f3fSDimitry Andric
12550b57cec5SDimitry Andric/// Simple arithmetic operations
12560b57cec5SDimitry Andric
12570b57cec5SDimitry Andricdef : PatGprGpr<add, ADD>;
12580b57cec5SDimitry Andricdef : PatGprSimm12<add, ADDI>;
12590b57cec5SDimitry Andricdef : PatGprGpr<sub, SUB>;
12600b57cec5SDimitry Andricdef : PatGprGpr<or, OR>;
12610b57cec5SDimitry Andricdef : PatGprSimm12<or, ORI>;
12620b57cec5SDimitry Andricdef : PatGprGpr<and, AND>;
12630b57cec5SDimitry Andricdef : PatGprSimm12<and, ANDI>;
12640b57cec5SDimitry Andricdef : PatGprGpr<xor, XOR>;
12650b57cec5SDimitry Andricdef : PatGprSimm12<xor, XORI>;
12660b57cec5SDimitry Andricdef : PatGprUimmLog2XLen<shl, SLLI>;
12670b57cec5SDimitry Andricdef : PatGprUimmLog2XLen<srl, SRLI>;
12680b57cec5SDimitry Andricdef : PatGprUimmLog2XLen<sra, SRAI>;
12690b57cec5SDimitry Andric
1270bdd1243dSDimitry Andric// Select 'or' as ADDI if the immediate bits are known to be 0 in $rs1. This
1271bdd1243dSDimitry Andric// can improve compressibility.
1272bdd1243dSDimitry Andricdef or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{
1273*0fca6ea1SDimitry Andric  if (N->getFlags().hasDisjoint())
1274*0fca6ea1SDimitry Andric    return true;
1275bdd1243dSDimitry Andric  KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0);
1276bdd1243dSDimitry Andric  KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0);
1277bdd1243dSDimitry Andric  return KnownBits::haveNoCommonBitsSet(Known0, Known1);
1278bdd1243dSDimitry Andric}]>;
1279bdd1243dSDimitry Andricdef : PatGprSimm12<or_is_add, ADDI>;
1280bdd1243dSDimitry Andric
1281*0fca6ea1SDimitry Andricdef add_like : PatFrags<(ops node:$lhs, node:$rhs),
1282*0fca6ea1SDimitry Andric                        [(or_is_add node:$lhs, node:$rhs),
1283*0fca6ea1SDimitry Andric                         (add  node:$lhs, node:$rhs)]>;
1284*0fca6ea1SDimitry Andric
1285bdd1243dSDimitry Andric// negate of low bit can be done via two (compressible) shifts.  The negate
1286bdd1243dSDimitry Andric// is never compressible since rs1 and rd can't be the same register.
1287bdd1243dSDimitry Andricdef : Pat<(XLenVT (sub 0, (and_oneuse GPR:$rs, 1))),
1288*0fca6ea1SDimitry Andric          (SRAI (XLenVT (SLLI $rs, (ImmSubFromXLen (XLenVT 1)))),
1289bdd1243dSDimitry Andric                (ImmSubFromXLen (XLenVT 1)))>;
1290bdd1243dSDimitry Andric
129181ad6265SDimitry Andric// AND with leading/trailing ones mask exceeding simm32/simm12.
129281ad6265SDimitry Andricdef : Pat<(i64 (and GPR:$rs, LeadingOnesMask:$mask)),
1293*0fca6ea1SDimitry Andric          (SLLI (i64 (SRLI $rs, LeadingOnesMask:$mask)), LeadingOnesMask:$mask)>;
129404eeddc0SDimitry Andricdef : Pat<(XLenVT (and GPR:$rs, TrailingOnesMask:$mask)),
1295*0fca6ea1SDimitry Andric          (SRLI (XLenVT (SLLI $rs, TrailingOnesMask:$mask)), TrailingOnesMask:$mask)>;
129604eeddc0SDimitry Andric
12970b57cec5SDimitry Andric// Match both a plain shift and one where the shift amount is masked (this is
12980b57cec5SDimitry Andric// typically introduced when the legalizer promotes the shift amount and
12990b57cec5SDimitry Andric// zero-extends it). For RISC-V, the mask is unnecessary as shifts in the base
13000b57cec5SDimitry Andric// ISA only read the least significant 5 bits (RV32I) or 6 bits (RV64I).
1301fe6060f1SDimitry Andricdef shiftMaskXLen : ComplexPattern<XLenVT, 1, "selectShiftMaskXLen", [], [], 0>;
1302fe6060f1SDimitry Andricdef shiftMask32   : ComplexPattern<i64, 1, "selectShiftMask32", [], [], 0>;
1303fe6060f1SDimitry Andric
13040b57cec5SDimitry Andricclass shiftop<SDPatternOperator operator>
1305fe6060f1SDimitry Andric    : PatFrag<(ops node:$val, node:$count),
1306fe6060f1SDimitry Andric              (operator node:$val, (XLenVT (shiftMaskXLen node:$count)))>;
1307e8d8bef9SDimitry Andricclass shiftopw<SDPatternOperator operator>
1308fe6060f1SDimitry Andric    : PatFrag<(ops node:$val, node:$count),
1309fe6060f1SDimitry Andric              (operator node:$val, (i64 (shiftMask32 node:$count)))>;
13100b57cec5SDimitry Andric
13110b57cec5SDimitry Andricdef : PatGprGpr<shiftop<shl>, SLL>;
13120b57cec5SDimitry Andricdef : PatGprGpr<shiftop<srl>, SRL>;
13130b57cec5SDimitry Andricdef : PatGprGpr<shiftop<sra>, SRA>;
13140b57cec5SDimitry Andric
13150b57cec5SDimitry Andric// This is a special case of the ADD instruction used to facilitate the use of a
13160b57cec5SDimitry Andric// fourth operand to emit a relocation on a symbol relating to this instruction.
13170b57cec5SDimitry Andric// The relocation does not affect any bits of the instruction itself but is used
13180b57cec5SDimitry Andric// as a hint to the linker.
13190b57cec5SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in
13200b57cec5SDimitry Andricdef PseudoAddTPRel : Pseudo<(outs GPR:$rd),
13210b57cec5SDimitry Andric                            (ins GPR:$rs1, GPR:$rs2, tprel_add_symbol:$src), [],
13220b57cec5SDimitry Andric                            "add", "$rd, $rs1, $rs2, $src">;
13230b57cec5SDimitry Andric
13240b57cec5SDimitry Andric/// FrameIndex calculations
13250b57cec5SDimitry Andric
132606c3fb27SDimitry Andricdef : Pat<(FrameAddrRegImm (iPTR GPR:$rs1), simm12:$imm12),
132781ad6265SDimitry Andric          (ADDI GPR:$rs1, simm12:$imm12)>;
132881ad6265SDimitry Andric
132981ad6265SDimitry Andric/// HI and ADD_LO address nodes.
133081ad6265SDimitry Andric
1331*0fca6ea1SDimitry Andric// Pseudo for a rematerializable LUI+ADDI sequence for loading an address.
1332*0fca6ea1SDimitry Andric// It will be expanded after register allocation.
1333*0fca6ea1SDimitry Andric// FIXME: The scheduling information does not reflect the multiple instructions.
1334*0fca6ea1SDimitry Andriclet Size = 8, isReMaterializable = 1 in
1335*0fca6ea1SDimitry Andricdef PseudoMovAddr : Pseudo<(outs GPR:$dst), (ins uimm20_lui:$hi, simm12:$lo), []>,
1336*0fca6ea1SDimitry Andric                    Sched<[WriteIALU]>;
1337*0fca6ea1SDimitry Andric
1338*0fca6ea1SDimitry Andricdef riscv_hi_oneuse : unop_oneuse<riscv_hi>;
1339*0fca6ea1SDimitry Andricdef addr_hi_lo : PatFrag<(ops node:$hi, node:$lo),
1340*0fca6ea1SDimitry Andric                         (riscv_add_lo (riscv_hi_oneuse node:$hi), node:$lo)>;
1341*0fca6ea1SDimitry Andric
1342*0fca6ea1SDimitry Andricdef : Pat<(addr_hi_lo tglobaladdr:$hi, tglobaladdr:$lo),
1343*0fca6ea1SDimitry Andric          (PseudoMovAddr tglobaladdr:$hi, tglobaladdr:$lo)>;
1344*0fca6ea1SDimitry Andricdef : Pat<(addr_hi_lo tblockaddress:$hi, tblockaddress:$lo),
1345*0fca6ea1SDimitry Andric          (PseudoMovAddr tblockaddress:$hi, tblockaddress:$lo)>;
1346*0fca6ea1SDimitry Andricdef : Pat<(addr_hi_lo tjumptable:$hi, tjumptable:$lo),
1347*0fca6ea1SDimitry Andric          (PseudoMovAddr tjumptable:$hi, tjumptable:$lo)>;
1348*0fca6ea1SDimitry Andricdef : Pat<(addr_hi_lo tconstpool:$hi, tconstpool:$lo),
1349*0fca6ea1SDimitry Andric          (PseudoMovAddr tconstpool:$hi, tconstpool:$lo)>;
1350*0fca6ea1SDimitry Andric
135181ad6265SDimitry Andricdef : Pat<(riscv_hi tglobaladdr:$in), (LUI tglobaladdr:$in)>;
135281ad6265SDimitry Andricdef : Pat<(riscv_hi tblockaddress:$in), (LUI tblockaddress:$in)>;
135381ad6265SDimitry Andricdef : Pat<(riscv_hi tjumptable:$in), (LUI tjumptable:$in)>;
135481ad6265SDimitry Andricdef : Pat<(riscv_hi tconstpool:$in), (LUI tconstpool:$in)>;
135581ad6265SDimitry Andric
135681ad6265SDimitry Andricdef : Pat<(riscv_add_lo GPR:$hi, tglobaladdr:$lo),
135781ad6265SDimitry Andric          (ADDI GPR:$hi, tglobaladdr:$lo)>;
135881ad6265SDimitry Andricdef : Pat<(riscv_add_lo GPR:$hi, tblockaddress:$lo),
135981ad6265SDimitry Andric          (ADDI GPR:$hi, tblockaddress:$lo)>;
136081ad6265SDimitry Andricdef : Pat<(riscv_add_lo GPR:$hi, tjumptable:$lo),
136181ad6265SDimitry Andric          (ADDI GPR:$hi, tjumptable:$lo)>;
136281ad6265SDimitry Andricdef : Pat<(riscv_add_lo GPR:$hi, tconstpool:$lo),
136381ad6265SDimitry Andric          (ADDI GPR:$hi, tconstpool:$lo)>;
136481ad6265SDimitry Andric
136581ad6265SDimitry Andric/// TLS address nodes.
136681ad6265SDimitry Andric
136781ad6265SDimitry Andricdef : Pat<(riscv_hi tglobaltlsaddr:$in), (LUI tglobaltlsaddr:$in)>;
136881ad6265SDimitry Andricdef : Pat<(riscv_add_tprel GPR:$rs1, GPR:$rs2, tglobaltlsaddr:$src),
136981ad6265SDimitry Andric          (PseudoAddTPRel GPR:$rs1, GPR:$rs2, tglobaltlsaddr:$src)>;
137081ad6265SDimitry Andricdef : Pat<(riscv_add_lo GPR:$src, tglobaltlsaddr:$lo),
137181ad6265SDimitry Andric          (ADDI GPR:$src, tglobaltlsaddr:$lo)>;
13720b57cec5SDimitry Andric
13730b57cec5SDimitry Andric/// Setcc
13740b57cec5SDimitry Andric
13750b57cec5SDimitry Andricdef : PatGprGpr<setlt, SLT>;
13760b57cec5SDimitry Andricdef : PatGprSimm12<setlt, SLTI>;
13770b57cec5SDimitry Andricdef : PatGprGpr<setult, SLTU>;
13780b57cec5SDimitry Andricdef : PatGprSimm12<setult, SLTIU>;
13790b57cec5SDimitry Andric
138006c3fb27SDimitry Andric// RISC-V doesn't have general instructions for integer setne/seteq, but we can
138106c3fb27SDimitry Andric// check for equality with 0. These ComplexPatterns rewrite the setne/seteq into
138206c3fb27SDimitry Andric// something that can be compared with 0.
138306c3fb27SDimitry Andric// These ComplexPatterns must be used in pairs.
138406c3fb27SDimitry Andricdef riscv_setne : ComplexPattern<XLenVT, 1, "selectSETNE", [setcc]>;
138506c3fb27SDimitry Andricdef riscv_seteq : ComplexPattern<XLenVT, 1, "selectSETEQ", [setcc]>;
138606c3fb27SDimitry Andric
13870b57cec5SDimitry Andric// Define pattern expansions for setcc operations that aren't directly
13880b57cec5SDimitry Andric// handled by a RISC-V instruction.
138906c3fb27SDimitry Andricdef : Pat<(riscv_seteq (XLenVT GPR:$rs1)), (SLTIU GPR:$rs1, 1)>;
139006c3fb27SDimitry Andricdef : Pat<(riscv_setne (XLenVT GPR:$rs1)), (SLTU (XLenVT X0), GPR:$rs1)>;
139106c3fb27SDimitry Andricdef : Pat<(XLenVT (setne (XLenVT GPR:$rs1), -1)), (SLTIU GPR:$rs1, -1)>;
1392fcaf7f86SDimitry Andric
1393349cc55cSDimitry Andricdef IntCCtoRISCVCC : SDNodeXForm<riscv_selectcc, [{
1394349cc55cSDimitry Andric  ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
1395349cc55cSDimitry Andric  RISCVCC::CondCode BrCC = getRISCVCCForIntCC(CC);
1396349cc55cSDimitry Andric  return CurDAG->getTargetConstant(BrCC, SDLoc(N), Subtarget->getXLenVT());
1397349cc55cSDimitry Andric}]>;
1398349cc55cSDimitry Andric
1399349cc55cSDimitry Andricdef riscv_selectcc_frag : PatFrag<(ops node:$lhs, node:$rhs, node:$cc,
1400349cc55cSDimitry Andric                                       node:$truev, node:$falsev),
1401349cc55cSDimitry Andric                                  (riscv_selectcc node:$lhs, node:$rhs,
1402349cc55cSDimitry Andric                                                  node:$cc, node:$truev,
1403349cc55cSDimitry Andric                                                  node:$falsev), [{}],
1404349cc55cSDimitry Andric                                  IntCCtoRISCVCC>;
1405349cc55cSDimitry Andric
140606c3fb27SDimitry Andricmulticlass SelectCC_GPR_rrirr<DAGOperand valty, ValueType vt> {
14070b57cec5SDimitry Andric  let usesCustomInserter = 1 in
1408bdd1243dSDimitry Andric  def _Using_CC_GPR : Pseudo<(outs valty:$dst),
1409bdd1243dSDimitry Andric                             (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
14100b57cec5SDimitry Andric                              valty:$truev, valty:$falsev),
1411349cc55cSDimitry Andric                             [(set valty:$dst,
141206c3fb27SDimitry Andric                               (riscv_selectcc_frag:$cc (XLenVT GPR:$lhs), GPR:$rhs, cond,
141306c3fb27SDimitry Andric                                                        (vt valty:$truev), valty:$falsev))]>;
1414bdd1243dSDimitry Andric  // Explicitly select 0 in the condition to X0. The register coalescer doesn't
1415bdd1243dSDimitry Andric  // always do it.
141606c3fb27SDimitry Andric  def : Pat<(riscv_selectcc_frag:$cc (XLenVT GPR:$lhs), 0, cond, (vt valty:$truev),
1417bdd1243dSDimitry Andric                                     valty:$falsev),
141806c3fb27SDimitry Andric            (!cast<Instruction>(NAME#"_Using_CC_GPR") GPR:$lhs, (XLenVT X0),
1419bdd1243dSDimitry Andric             (IntCCtoRISCVCC $cc), valty:$truev, valty:$falsev)>;
1420bdd1243dSDimitry Andric}
14210b57cec5SDimitry Andric
14221db9f3b2SDimitry Andriclet Predicates = [NoConditionalMoveFusion] in
142306c3fb27SDimitry Andricdefm Select_GPR : SelectCC_GPR_rrirr<GPR, XLenVT>;
1424bdd1243dSDimitry Andric
142506c3fb27SDimitry Andricclass SelectCompressOpt<CondCode Cond>
142606c3fb27SDimitry Andric    : Pat<(riscv_selectcc_frag:$select (XLenVT GPR:$lhs), simm12_no6:$Constant, Cond,
142706c3fb27SDimitry Andric                                       (XLenVT GPR:$truev), GPR:$falsev),
1428*0fca6ea1SDimitry Andric    (Select_GPR_Using_CC_GPR (XLenVT (ADDI GPR:$lhs, (NegImm simm12:$Constant))), (XLenVT X0),
1429bdd1243dSDimitry Andric                          (IntCCtoRISCVCC $select), GPR:$truev, GPR:$falsev)>;
1430bdd1243dSDimitry Andric
1431bdd1243dSDimitry Andricdef OptForMinSize : Predicate<"MF ? MF->getFunction().hasMinSize() : false">;
1432bdd1243dSDimitry Andric
1433bdd1243dSDimitry Andriclet Predicates = [HasStdExtC, OptForMinSize] in {
1434bdd1243dSDimitry Andric  def : SelectCompressOpt<SETEQ>;
1435bdd1243dSDimitry Andric  def : SelectCompressOpt<SETNE>;
1436bdd1243dSDimitry Andric}
14370b57cec5SDimitry Andric
14380b57cec5SDimitry Andric/// Branches and jumps
14390b57cec5SDimitry Andric
1440fe6060f1SDimitry Andric// Match `riscv_brcc` and lower to the appropriate RISC-V branch instruction.
1441bdd1243dSDimitry Andricmulticlass BccPat<CondCode Cond, RVInstB Inst> {
144206c3fb27SDimitry Andric  def : Pat<(riscv_brcc (XLenVT GPR:$rs1), GPR:$rs2, Cond, bb:$imm12),
14430b57cec5SDimitry Andric            (Inst GPR:$rs1, GPR:$rs2, simm13_lsb0:$imm12)>;
1444bdd1243dSDimitry Andric  // Explicitly select 0 to X0. The register coalescer doesn't always do it.
144506c3fb27SDimitry Andric  def : Pat<(riscv_brcc (XLenVT GPR:$rs1), 0, Cond, bb:$imm12),
144606c3fb27SDimitry Andric            (Inst GPR:$rs1, (XLenVT X0), simm13_lsb0:$imm12)>;
1447bdd1243dSDimitry Andric}
14480b57cec5SDimitry Andric
144906c3fb27SDimitry Andricclass BrccCompressOpt<CondCode Cond, RVInstB Inst>
145006c3fb27SDimitry Andric    : Pat<(riscv_brcc GPR:$lhs, simm12_no6:$Constant, Cond, bb:$place),
1451*0fca6ea1SDimitry Andric          (Inst (XLenVT (ADDI GPR:$lhs, (NegImm simm12:$Constant))),
1452*0fca6ea1SDimitry Andric                (XLenVT X0), bb:$place)>;
1453bdd1243dSDimitry Andric
1454bdd1243dSDimitry Andricdefm : BccPat<SETEQ, BEQ>;
1455bdd1243dSDimitry Andricdefm : BccPat<SETNE, BNE>;
1456bdd1243dSDimitry Andricdefm : BccPat<SETLT, BLT>;
1457bdd1243dSDimitry Andricdefm : BccPat<SETGE, BGE>;
1458bdd1243dSDimitry Andricdefm : BccPat<SETULT, BLTU>;
1459bdd1243dSDimitry Andricdefm : BccPat<SETUGE, BGEU>;
1460bdd1243dSDimitry Andric
1461*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtCOrZca, OptForMinSize] in {
146206c3fb27SDimitry Andric  def : BrccCompressOpt<SETEQ, BEQ>;
146306c3fb27SDimitry Andric  def : BrccCompressOpt<SETNE, BNE>;
1464bdd1243dSDimitry Andric}
14650b57cec5SDimitry Andric
146606c3fb27SDimitry Andricclass LongBccPseudo : Pseudo<(outs),
146706c3fb27SDimitry Andric                             (ins GPR:$rs1, GPR:$rs2, simm21_lsb0_jal:$imm20),
146806c3fb27SDimitry Andric                             []> {
146906c3fb27SDimitry Andric  let Size = 8;
147006c3fb27SDimitry Andric  let isBarrier = 1;
147106c3fb27SDimitry Andric  let isBranch = 1;
147206c3fb27SDimitry Andric  let hasSideEffects = 0;
147306c3fb27SDimitry Andric  let mayStore = 0;
147406c3fb27SDimitry Andric  let mayLoad = 0;
147506c3fb27SDimitry Andric  let isAsmParserOnly = 1;
147606c3fb27SDimitry Andric  let hasNoSchedulingInfo = 1;
147706c3fb27SDimitry Andric}
147806c3fb27SDimitry Andric
147906c3fb27SDimitry Andricdef PseudoLongBEQ : LongBccPseudo;
148006c3fb27SDimitry Andricdef PseudoLongBNE : LongBccPseudo;
148106c3fb27SDimitry Andricdef PseudoLongBLT : LongBccPseudo;
148206c3fb27SDimitry Andricdef PseudoLongBGE : LongBccPseudo;
148306c3fb27SDimitry Andricdef PseudoLongBLTU : LongBccPseudo;
148406c3fb27SDimitry Andricdef PseudoLongBGEU : LongBccPseudo;
148506c3fb27SDimitry Andric
14860b57cec5SDimitry Andriclet isBarrier = 1, isBranch = 1, isTerminator = 1 in
14870b57cec5SDimitry Andricdef PseudoBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>,
14880b57cec5SDimitry Andric               PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>;
14890b57cec5SDimitry Andric
1490*0fca6ea1SDimitry Andriclet Predicates = [NoStdExtZicfilp],
1491*0fca6ea1SDimitry Andric    isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in
1492fe6060f1SDimitry Andricdef PseudoBRIND : Pseudo<(outs), (ins GPRJALR:$rs1, simm12:$imm12), []>,
14930b57cec5SDimitry Andric                  PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>;
14940b57cec5SDimitry Andric
1495*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZicfilp],
1496*0fca6ea1SDimitry Andric    isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in {
1497*0fca6ea1SDimitry Andricdef PseudoBRINDNonX7 : Pseudo<(outs), (ins GPRJALRNonX7:$rs1, simm12:$imm12), []>,
1498*0fca6ea1SDimitry Andric                       PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>;
1499*0fca6ea1SDimitry Andricdef PseudoBRINDX7 : Pseudo<(outs), (ins GPRX7:$rs1, simm12:$imm12), []>,
1500*0fca6ea1SDimitry Andric                    PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>;
1501*0fca6ea1SDimitry Andric}
1502*0fca6ea1SDimitry Andric
1503*0fca6ea1SDimitry Andric// For Zicfilp, need to avoid using X7/T2 for indirect branches which need
1504*0fca6ea1SDimitry Andric// landing pad.
1505*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZicfilp] in {
1506*0fca6ea1SDimitry Andricdef : Pat<(brind GPRJALRNonX7:$rs1), (PseudoBRINDNonX7 GPRJALRNonX7:$rs1, 0)>;
1507*0fca6ea1SDimitry Andricdef : Pat<(brind (add GPRJALRNonX7:$rs1, simm12:$imm12)),
1508*0fca6ea1SDimitry Andric          (PseudoBRINDNonX7 GPRJALRNonX7:$rs1, simm12:$imm12)>;
1509*0fca6ea1SDimitry Andric
1510*0fca6ea1SDimitry Andricdef : Pat<(riscv_sw_guarded_brind GPRX7:$rs1), (PseudoBRINDX7 GPRX7:$rs1, 0)>;
1511*0fca6ea1SDimitry Andricdef : Pat<(riscv_sw_guarded_brind (add GPRX7:$rs1, simm12:$imm12)),
1512*0fca6ea1SDimitry Andric          (PseudoBRINDX7 GPRX7:$rs1, simm12:$imm12)>;
1513*0fca6ea1SDimitry Andric}
1514*0fca6ea1SDimitry Andric
1515*0fca6ea1SDimitry Andriclet Predicates = [NoStdExtZicfilp] in {
1516fe6060f1SDimitry Andricdef : Pat<(brind GPRJALR:$rs1), (PseudoBRIND GPRJALR:$rs1, 0)>;
1517fe6060f1SDimitry Andricdef : Pat<(brind (add GPRJALR:$rs1, simm12:$imm12)),
1518fe6060f1SDimitry Andric          (PseudoBRIND GPRJALR:$rs1, simm12:$imm12)>;
1519*0fca6ea1SDimitry Andric}
15200b57cec5SDimitry Andric
1521480093f4SDimitry Andric// PseudoCALLReg is a generic pseudo instruction for calls which will eventually
15220b57cec5SDimitry Andric// expand to auipc and jalr while encoding, with any given register used as the
15230b57cec5SDimitry Andric// destination.
15240b57cec5SDimitry Andric// Define AsmString to print "call" when compile with -S flag.
15250b57cec5SDimitry Andric// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction.
15261fd87a68SDimitry Andriclet isCall = 1, isBarrier = 1, isCodeGenOnly = 0, Size = 8, hasSideEffects = 0,
15270b57cec5SDimitry Andric    mayStore = 0, mayLoad = 0 in
152806c3fb27SDimitry Andricdef PseudoCALLReg : Pseudo<(outs GPR:$rd), (ins call_symbol:$func), [],
152906c3fb27SDimitry Andric                           "call", "$rd, $func">,
153006c3fb27SDimitry Andric                    Sched<[WriteIALU, WriteJalr, ReadJalr]>;
15310b57cec5SDimitry Andric
15320b57cec5SDimitry Andric// PseudoCALL is a pseudo instruction which will eventually expand to auipc
15330b57cec5SDimitry Andric// and jalr while encoding. This is desirable, as an auipc+jalr pair with
15340b57cec5SDimitry Andric// R_RISCV_CALL and R_RISCV_RELAX relocations can be be relaxed by the linker
15350b57cec5SDimitry Andric// if the offset fits in a signed 21-bit immediate.
15360b57cec5SDimitry Andric// Define AsmString to print "call" when compile with -S flag.
15370b57cec5SDimitry Andric// Define isCodeGenOnly = 0 to support parsing assembly "call" instruction.
15381fd87a68SDimitry Andriclet isCall = 1, Defs = [X1], isCodeGenOnly = 0, Size = 8 in
153906c3fb27SDimitry Andricdef PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), [],
154006c3fb27SDimitry Andric                        "call", "$func">,
154106c3fb27SDimitry Andric                 Sched<[WriteIALU, WriteJalr, ReadJalr]>;
15420b57cec5SDimitry Andric
15430b57cec5SDimitry Andricdef : Pat<(riscv_call tglobaladdr:$func), (PseudoCALL tglobaladdr:$func)>;
15440b57cec5SDimitry Andricdef : Pat<(riscv_call texternalsym:$func), (PseudoCALL texternalsym:$func)>;
15450b57cec5SDimitry Andric
154606c3fb27SDimitry Andricdef : Pat<(riscv_sret_glue), (SRET (XLenVT X0), (XLenVT X0))>;
154706c3fb27SDimitry Andricdef : Pat<(riscv_mret_glue), (MRET (XLenVT X0), (XLenVT X0))>;
15480b57cec5SDimitry Andric
1549*0fca6ea1SDimitry Andriclet isCall = 1, Defs = [X1] in {
1550*0fca6ea1SDimitry Andriclet Predicates = [NoStdExtZicfilp] in
1551fe6060f1SDimitry Andricdef PseudoCALLIndirect : Pseudo<(outs), (ins GPRJALR:$rs1),
1552fe6060f1SDimitry Andric                                [(riscv_call GPRJALR:$rs1)]>,
15530b57cec5SDimitry Andric                         PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>;
1554*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZicfilp] in
1555*0fca6ea1SDimitry Andricdef PseudoCALLIndirectNonX7 : Pseudo<(outs), (ins GPRJALRNonX7:$rs1),
1556*0fca6ea1SDimitry Andric                                     [(riscv_call GPRJALRNonX7:$rs1)]>,
1557*0fca6ea1SDimitry Andric                              PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>;
1558*0fca6ea1SDimitry Andric}
15590b57cec5SDimitry Andric
15600b57cec5SDimitry Andriclet isBarrier = 1, isReturn = 1, isTerminator = 1 in
156106c3fb27SDimitry Andricdef PseudoRET : Pseudo<(outs), (ins), [(riscv_ret_glue)]>,
15620b57cec5SDimitry Andric                PseudoInstExpansion<(JALR X0, X1, 0)>;
15630b57cec5SDimitry Andric
15640b57cec5SDimitry Andric// PseudoTAIL is a pseudo instruction similar to PseudoCALL and will eventually
15650b57cec5SDimitry Andric// expand to auipc and jalr while encoding.
15660b57cec5SDimitry Andric// Define AsmString to print "tail" when compile with -S flag.
15670b57cec5SDimitry Andriclet isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2],
15681fd87a68SDimitry Andric    Size = 8, isCodeGenOnly = 0 in
156906c3fb27SDimitry Andricdef PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), [],
157006c3fb27SDimitry Andric                        "tail", "$dst">,
157106c3fb27SDimitry Andric                 Sched<[WriteIALU, WriteJalr, ReadJalr]>;
15720b57cec5SDimitry Andric
1573*0fca6ea1SDimitry Andriclet isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in {
1574*0fca6ea1SDimitry Andriclet Predicates = [NoStdExtZicfilp] in
15750b57cec5SDimitry Andricdef PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1),
15760b57cec5SDimitry Andric                                [(riscv_tail GPRTC:$rs1)]>,
15770b57cec5SDimitry Andric                         PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>;
1578*0fca6ea1SDimitry Andriclet Predicates = [HasStdExtZicfilp] in
1579*0fca6ea1SDimitry Andricdef PseudoTAILIndirectNonX7 : Pseudo<(outs), (ins GPRTCNonX7:$rs1),
1580*0fca6ea1SDimitry Andric                                     [(riscv_tail GPRTCNonX7:$rs1)]>,
1581*0fca6ea1SDimitry Andric                              PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>;
1582*0fca6ea1SDimitry Andric}
15830b57cec5SDimitry Andric
15840b57cec5SDimitry Andricdef : Pat<(riscv_tail (iPTR tglobaladdr:$dst)),
158581ad6265SDimitry Andric          (PseudoTAIL tglobaladdr:$dst)>;
15860b57cec5SDimitry Andricdef : Pat<(riscv_tail (iPTR texternalsym:$dst)),
15870b57cec5SDimitry Andric          (PseudoTAIL texternalsym:$dst)>;
15880b57cec5SDimitry Andric
15891fd87a68SDimitry Andriclet isCall = 0, isBarrier = 1, isBranch = 1, isTerminator = 1, Size = 8,
159075b4d546SDimitry Andric    isCodeGenOnly = 0, hasSideEffects = 0, mayStore = 0, mayLoad = 0 in
159106c3fb27SDimitry Andricdef PseudoJump : Pseudo<(outs GPR:$rd), (ins pseudo_jump_symbol:$target), [],
159206c3fb27SDimitry Andric                        "jump", "$target, $rd">,
159306c3fb27SDimitry Andric                 Sched<[WriteIALU, WriteJalr, ReadJalr]>;
15945ffd83dbSDimitry Andric
15955f757f3fSDimitry Andric// Pseudo for a rematerializable constant materialization sequence.
15965f757f3fSDimitry Andric// This is an experimental feature enabled by
15975f757f3fSDimitry Andric// -riscv-use-rematerializable-movimm in RISCVISelDAGToDAG.cpp
15985f757f3fSDimitry Andric// It will be expanded after register allocation.
15995f757f3fSDimitry Andric// FIXME: The scheduling information does not reflect the multiple instructions.
1600*0fca6ea1SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8,
1601*0fca6ea1SDimitry Andric    isReMaterializable = 1 in
16025f757f3fSDimitry Andricdef PseudoMovImm : Pseudo<(outs GPR:$dst), (ins i32imm:$imm), []>,
16035f757f3fSDimitry Andric                   Sched<[WriteIALU]>;
16045f757f3fSDimitry Andric
16051fd87a68SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0,
16060b57cec5SDimitry Andric    isAsmParserOnly = 1 in
16070b57cec5SDimitry Andricdef PseudoLLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
16080b57cec5SDimitry Andric                       "lla", "$dst, $src">;
16090b57cec5SDimitry Andric
161006c3fb27SDimitry Andric// Refer to comment on PseudoLI for explanation of Size=32
161106c3fb27SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0,
161206c3fb27SDimitry Andric    isAsmParserOnly = 1 in
161306c3fb27SDimitry Andricdef PseudoLLAImm : Pseudo<(outs GPR:$dst), (ins ixlenimm_li_restricted:$imm), [],
161406c3fb27SDimitry Andric                          "lla", "$dst, $imm">;
161581ad6265SDimitry Andricdef : Pat<(riscv_lla tglobaladdr:$in), (PseudoLLA tglobaladdr:$in)>;
161681ad6265SDimitry Andricdef : Pat<(riscv_lla tblockaddress:$in), (PseudoLLA tblockaddress:$in)>;
161781ad6265SDimitry Andricdef : Pat<(riscv_lla tjumptable:$in), (PseudoLLA tjumptable:$in)>;
161881ad6265SDimitry Andricdef : Pat<(riscv_lla tconstpool:$in), (PseudoLLA tconstpool:$in)>;
161981ad6265SDimitry Andric
16201fd87a68SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0,
16210b57cec5SDimitry Andric    isAsmParserOnly = 1 in
162206c3fb27SDimitry Andricdef PseudoLGA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
162306c3fb27SDimitry Andric                       "lga", "$dst, $src">;
162406c3fb27SDimitry Andric
162506c3fb27SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0,
162606c3fb27SDimitry Andric    isAsmParserOnly = 1 in
16270b57cec5SDimitry Andricdef PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
16280b57cec5SDimitry Andric                      "la", "$dst, $src">;
16290b57cec5SDimitry Andric
163006c3fb27SDimitry Andric// Refer to comment on PseudoLI for explanation of Size=32
163106c3fb27SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32,
163206c3fb27SDimitry Andric    isCodeGenOnly = 0, isAsmParserOnly = 1 in
163306c3fb27SDimitry Andricdef PseudoLAImm : Pseudo<(outs GPR:$rd), (ins ixlenimm_li_restricted:$imm), [],
163406c3fb27SDimitry Andric                         "la", "$rd, $imm">;
163581ad6265SDimitry Andric
16361fd87a68SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0,
16370b57cec5SDimitry Andric    isAsmParserOnly = 1 in
16380b57cec5SDimitry Andricdef PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
16390b57cec5SDimitry Andric                             "la.tls.ie", "$dst, $src">;
16400b57cec5SDimitry Andric
164181ad6265SDimitry Andriclet hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8, isCodeGenOnly = 0,
16420b57cec5SDimitry Andric    isAsmParserOnly = 1 in
16430b57cec5SDimitry Andricdef PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
16440b57cec5SDimitry Andric                             "la.tls.gd", "$dst, $src">;
16450b57cec5SDimitry Andric
16467a6dacacSDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 32, isCodeGenOnly = 0 in
16477a6dacacSDimitry Andricdef PseudoLA_TLSDESC : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
16487a6dacacSDimitry Andric                             "la.tlsdesc", "$dst, $src">;
16497a6dacacSDimitry Andric
16507a6dacacSDimitry Andricdef TLSDESCCallSymbol : AsmOperandClass {
16517a6dacacSDimitry Andric  let Name = "TLSDESCCallSymbol";
16527a6dacacSDimitry Andric  let RenderMethod = "addImmOperands";
16537a6dacacSDimitry Andric  let DiagnosticType = "InvalidTLSDESCCallSymbol";
16547a6dacacSDimitry Andric  let ParserMethod = "parseOperandWithModifier";
16557a6dacacSDimitry Andric}
16567a6dacacSDimitry Andric
16577a6dacacSDimitry Andric// A bare symbol with the %tlsdesc_call variant.
16587a6dacacSDimitry Andricdef tlsdesc_call_symbol : Operand<XLenVT> {
16597a6dacacSDimitry Andric  let ParserMatchClass = TLSDESCCallSymbol;
16607a6dacacSDimitry Andric}
16617a6dacacSDimitry Andric// This is a special case of the JALR instruction used to facilitate the use of a
16627a6dacacSDimitry Andric// fourth operand to emit a relocation on a symbol relating to this instruction.
16637a6dacacSDimitry Andric// The relocation does not affect any bits of the instruction itself but is used
16647a6dacacSDimitry Andric// as a hint to the linker.
16657a6dacacSDimitry Andriclet isCall = 1, isBarrier = 1, isCodeGenOnly = 0, Size = 8, hasSideEffects = 0,
16667a6dacacSDimitry Andric    mayStore = 0, mayLoad = 0 in
16677a6dacacSDimitry Andricdef PseudoTLSDESCCall : Pseudo<(outs GPR:$rd),
16687a6dacacSDimitry Andric                         (ins GPR:$rs1, simm12:$imm12, tlsdesc_call_symbol:$src), [],
16697a6dacacSDimitry Andric                         "jalr", "$rd, ${imm12}(${rs1}), $src">,
16707a6dacacSDimitry Andric                         Sched<[WriteJalr, ReadJalr]> {
16717a6dacacSDimitry Andric  let Defs = [X10];
16727a6dacacSDimitry Andric  let Uses = [X10];
16737a6dacacSDimitry Andric}
16747a6dacacSDimitry Andric
1675e8d8bef9SDimitry Andric
1676e8d8bef9SDimitry Andric/// Sign/Zero Extends
1677e8d8bef9SDimitry Andric
1678e8d8bef9SDimitry Andric// There are single-instruction versions of these in Zbb, so disable these
1679e8d8bef9SDimitry Andric// Pseudos if that extension is present.
1680e8d8bef9SDimitry Andriclet hasSideEffects = 0, mayLoad = 0,
1681e8d8bef9SDimitry Andric    mayStore = 0, isCodeGenOnly = 0, isAsmParserOnly = 1 in {
1682e8d8bef9SDimitry Andricdef PseudoSEXT_B : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.b", "$rd, $rs">;
1683e8d8bef9SDimitry Andricdef PseudoSEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "sext.h", "$rd, $rs">;
1684e8d8bef9SDimitry Andric// rv64's sext.w is defined above, using InstAlias<"sext.w ...
1685e8d8bef9SDimitry Andric// zext.b is defined above, using InstAlias<"zext.b ...
1686e8d8bef9SDimitry Andricdef PseudoZEXT_H : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.h", "$rd, $rs">;
1687e8d8bef9SDimitry Andric} // hasSideEffects = 0, ...
1688e8d8bef9SDimitry Andric
1689e8d8bef9SDimitry Andriclet Predicates = [IsRV64], hasSideEffects = 0, mayLoad = 0, mayStore = 0,
1690e8d8bef9SDimitry Andric  isCodeGenOnly = 0, isAsmParserOnly = 1 in {
1691e8d8bef9SDimitry Andricdef PseudoZEXT_W : Pseudo<(outs GPR:$rd), (ins GPR:$rs), [], "zext.w", "$rd, $rs">;
1692e8d8bef9SDimitry Andric} // Predicates = [IsRV64], ...
1693e8d8bef9SDimitry Andric
16940b57cec5SDimitry Andric/// Loads
16950b57cec5SDimitry Andric
169606c3fb27SDimitry Andricclass LdPat<PatFrag LoadOp, RVInst Inst, ValueType vt = XLenVT>
169706c3fb27SDimitry Andric    : Pat<(vt (LoadOp (AddrRegImm (XLenVT GPR:$rs1), simm12:$imm12))),
169881ad6265SDimitry Andric          (Inst GPR:$rs1, simm12:$imm12)>;
16990b57cec5SDimitry Andric
170006c3fb27SDimitry Andricdef : LdPat<sextloadi8, LB>;
170106c3fb27SDimitry Andricdef : LdPat<extloadi8, LBU>; // Prefer unsigned due to no c.lb in Zcb.
170206c3fb27SDimitry Andricdef : LdPat<sextloadi16, LH>;
170306c3fb27SDimitry Andricdef : LdPat<extloadi16, LH>;
17045f757f3fSDimitry Andricdef : LdPat<load, LW, i32>;
170506c3fb27SDimitry Andricdef : LdPat<zextloadi8, LBU>;
170606c3fb27SDimitry Andricdef : LdPat<zextloadi16, LHU>;
17070b57cec5SDimitry Andric
17080b57cec5SDimitry Andric/// Stores
17090b57cec5SDimitry Andric
171006c3fb27SDimitry Andricclass StPat<PatFrag StoreOp, RVInst Inst, RegisterClass StTy,
171106c3fb27SDimitry Andric            ValueType vt>
171206c3fb27SDimitry Andric    : Pat<(StoreOp (vt StTy:$rs2), (AddrRegImm (XLenVT GPR:$rs1),
171306c3fb27SDimitry Andric                   simm12:$imm12)),
171481ad6265SDimitry Andric          (Inst StTy:$rs2, GPR:$rs1, simm12:$imm12)>;
17150b57cec5SDimitry Andric
171606c3fb27SDimitry Andricdef : StPat<truncstorei8, SB, GPR, XLenVT>;
171706c3fb27SDimitry Andricdef : StPat<truncstorei16, SH, GPR, XLenVT>;
17185f757f3fSDimitry Andricdef : StPat<store, SW, GPR, i32>;
17190b57cec5SDimitry Andric
17200b57cec5SDimitry Andric/// Fences
17210b57cec5SDimitry Andric
17220b57cec5SDimitry Andric// Refer to Table A.6 in the version 2.3 draft of the RISC-V Instruction Set
17230b57cec5SDimitry Andric// Manual: Volume I.
17240b57cec5SDimitry Andric
17250b57cec5SDimitry Andric// fence acquire -> fence r, rw
1726480093f4SDimitry Andricdef : Pat<(atomic_fence (XLenVT 4), (timm)), (FENCE 0b10, 0b11)>;
17270b57cec5SDimitry Andric// fence release -> fence rw, w
1728480093f4SDimitry Andricdef : Pat<(atomic_fence (XLenVT 5), (timm)), (FENCE 0b11, 0b1)>;
17290b57cec5SDimitry Andric// fence acq_rel -> fence.tso
1730480093f4SDimitry Andricdef : Pat<(atomic_fence (XLenVT 6), (timm)), (FENCE_TSO)>;
17310b57cec5SDimitry Andric// fence seq_cst -> fence rw, rw
1732480093f4SDimitry Andricdef : Pat<(atomic_fence (XLenVT 7), (timm)), (FENCE 0b11, 0b11)>;
17330b57cec5SDimitry Andric
17340b57cec5SDimitry Andric// Lowering for atomic load and store is defined in RISCVInstrInfoA.td.
17350b57cec5SDimitry Andric// Although these are lowered to fence+load/store instructions defined in the
17360b57cec5SDimitry Andric// base RV32I/RV64I ISA, this lowering is only used when the A extension is
17370b57cec5SDimitry Andric// present. This is necessary as it isn't valid to mix __atomic_* libcalls
17380b57cec5SDimitry Andric// with inline atomic operations for the same object.
17390b57cec5SDimitry Andric
1740fe6060f1SDimitry Andric/// Access to system registers
1741fe6060f1SDimitry Andric
1742fe6060f1SDimitry Andric// Helpers for defining specific operations. They are defined for each system
1743fe6060f1SDimitry Andric// register separately. Side effect is not used because dependencies are
1744fe6060f1SDimitry Andric// expressed via use-def properties.
1745fe6060f1SDimitry Andric
1746fe6060f1SDimitry Andricclass ReadSysReg<SysReg SR, list<Register> Regs>
1747fe6060f1SDimitry Andric  : Pseudo<(outs GPR:$rd), (ins),
174806c3fb27SDimitry Andric           [(set GPR:$rd, (XLenVT (riscv_read_csr (XLenVT SR.Encoding))))]>,
1749fe6060f1SDimitry Andric    PseudoInstExpansion<(CSRRS GPR:$rd, SR.Encoding, X0)> {
1750fe6060f1SDimitry Andric  let hasSideEffects = 0;
1751fe6060f1SDimitry Andric  let Uses = Regs;
1752fe6060f1SDimitry Andric}
1753fe6060f1SDimitry Andric
1754fe6060f1SDimitry Andricclass WriteSysReg<SysReg SR, list<Register> Regs>
1755fe6060f1SDimitry Andric  : Pseudo<(outs), (ins GPR:$val),
175606c3fb27SDimitry Andric           [(riscv_write_csr (XLenVT SR.Encoding), (XLenVT GPR:$val))]>,
1757fe6060f1SDimitry Andric    PseudoInstExpansion<(CSRRW X0, SR.Encoding, GPR:$val)> {
1758fe6060f1SDimitry Andric  let hasSideEffects = 0;
1759fe6060f1SDimitry Andric  let Defs = Regs;
1760fe6060f1SDimitry Andric}
1761fe6060f1SDimitry Andric
1762fe6060f1SDimitry Andricclass WriteSysRegImm<SysReg SR, list<Register> Regs>
1763fe6060f1SDimitry Andric  : Pseudo<(outs), (ins uimm5:$val),
1764fe6060f1SDimitry Andric           [(riscv_write_csr (XLenVT SR.Encoding), uimm5:$val)]>,
1765fe6060f1SDimitry Andric    PseudoInstExpansion<(CSRRWI X0, SR.Encoding, uimm5:$val)> {
1766fe6060f1SDimitry Andric  let hasSideEffects = 0;
1767fe6060f1SDimitry Andric  let Defs = Regs;
1768fe6060f1SDimitry Andric}
1769fe6060f1SDimitry Andric
1770fe6060f1SDimitry Andricclass SwapSysReg<SysReg SR, list<Register> Regs>
1771fe6060f1SDimitry Andric  : Pseudo<(outs GPR:$rd), (ins GPR:$val),
177206c3fb27SDimitry Andric           [(set GPR:$rd, (riscv_swap_csr (XLenVT SR.Encoding), (XLenVT GPR:$val)))]>,
1773fe6060f1SDimitry Andric    PseudoInstExpansion<(CSRRW GPR:$rd, SR.Encoding, GPR:$val)> {
1774fe6060f1SDimitry Andric  let hasSideEffects = 0;
1775fe6060f1SDimitry Andric  let Uses = Regs;
1776fe6060f1SDimitry Andric  let Defs = Regs;
1777fe6060f1SDimitry Andric}
1778fe6060f1SDimitry Andric
1779fe6060f1SDimitry Andricclass SwapSysRegImm<SysReg SR, list<Register> Regs>
1780fe6060f1SDimitry Andric  : Pseudo<(outs GPR:$rd), (ins uimm5:$val),
178106c3fb27SDimitry Andric           [(set GPR:$rd, (XLenVT (riscv_swap_csr (XLenVT SR.Encoding), uimm5:$val)))]>,
1782fe6060f1SDimitry Andric    PseudoInstExpansion<(CSRRWI GPR:$rd, SR.Encoding, uimm5:$val)> {
1783fe6060f1SDimitry Andric  let hasSideEffects = 0;
1784fe6060f1SDimitry Andric  let Uses = Regs;
1785fe6060f1SDimitry Andric  let Defs = Regs;
1786fe6060f1SDimitry Andric}
1787fe6060f1SDimitry Andric
1788fe6060f1SDimitry Andricdef ReadFRM : ReadSysReg<SysRegFRM, [FRM]>;
1789fe6060f1SDimitry Andricdef WriteFRM : WriteSysReg<SysRegFRM, [FRM]>;
1790fe6060f1SDimitry Andricdef WriteFRMImm : WriteSysRegImm<SysRegFRM, [FRM]>;
1791bdd1243dSDimitry Andricdef SwapFRMImm : SwapSysRegImm<SysRegFRM, [FRM]>;
1792fe6060f1SDimitry Andric
179306c3fb27SDimitry Andricdef WriteVXRMImm : WriteSysRegImm<SysRegVXRM, [VXRM]>;
179406c3fb27SDimitry Andric
179504eeddc0SDimitry Andriclet hasSideEffects = true in {
179604eeddc0SDimitry Andricdef ReadFFLAGS : ReadSysReg<SysRegFFLAGS, [FFLAGS]>;
179704eeddc0SDimitry Andricdef WriteFFLAGS : WriteSysReg<SysRegFFLAGS, [FFLAGS]>;
179804eeddc0SDimitry Andric}
17990b57cec5SDimitry Andric/// Other pseudo-instructions
18000b57cec5SDimitry Andric
18010b57cec5SDimitry Andric// Pessimistically assume the stack pointer will be clobbered
18020b57cec5SDimitry Andriclet Defs = [X2], Uses = [X2] in {
18030b57cec5SDimitry Andricdef ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
18040b57cec5SDimitry Andric                              [(callseq_start timm:$amt1, timm:$amt2)]>;
18050b57cec5SDimitry Andricdef ADJCALLSTACKUP   : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
18060b57cec5SDimitry Andric                              [(callseq_end timm:$amt1, timm:$amt2)]>;
18070b57cec5SDimitry Andric} // Defs = [X2], Uses = [X2]
18080b57cec5SDimitry Andric
18090b57cec5SDimitry Andric/// RV64 patterns
18100b57cec5SDimitry Andric
1811e8d8bef9SDimitry Andriclet Predicates = [IsRV64, NotHasStdExtZba] in {
1812*0fca6ea1SDimitry Andricdef : Pat<(i64 (and GPR:$rs1, 0xffffffff)), (SRLI (i64 (SLLI GPR:$rs1, 32)), 32)>;
1813e8d8bef9SDimitry Andric
1814e8d8bef9SDimitry Andric// If we're shifting a 32-bit zero extended value left by 0-31 bits, use 2
1815e8d8bef9SDimitry Andric// shifts instead of 3. This can occur when unsigned is used to index an array.
1816fe6060f1SDimitry Andricdef : Pat<(i64 (shl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)),
1817*0fca6ea1SDimitry Andric          (SRLI (i64 (SLLI GPR:$rs1, 32)), (ImmSubFrom32 uimm5:$shamt))>;
1818e8d8bef9SDimitry Andric}
1819e8d8bef9SDimitry Andric
18205f757f3fSDimitry Andricclass binop_allhusers<SDPatternOperator operator>
18215f757f3fSDimitry Andric    : PatFrag<(ops node:$lhs, node:$rhs),
18225f757f3fSDimitry Andric              (XLenVT (operator node:$lhs, node:$rhs)), [{
18235f757f3fSDimitry Andric  return hasAllHUsers(Node);
18245f757f3fSDimitry Andric}]>;
18255f757f3fSDimitry Andric
1826349cc55cSDimitry Andric// PatFrag to allow ADDW/SUBW/MULW/SLLW to be selected from i64 add/sub/mul/shl
1827349cc55cSDimitry Andric// if only the lower 32 bits of their result is used.
1828349cc55cSDimitry Andricclass binop_allwusers<SDPatternOperator operator>
1829349cc55cSDimitry Andric    : PatFrag<(ops node:$lhs, node:$rhs),
183081ad6265SDimitry Andric              (i64 (operator node:$lhs, node:$rhs)), [{
1831349cc55cSDimitry Andric  return hasAllWUsers(Node);
1832349cc55cSDimitry Andric}]>;
1833349cc55cSDimitry Andric
1834349cc55cSDimitry Andricdef sexti32_allwusers : PatFrag<(ops node:$src),
1835349cc55cSDimitry Andric                                (sext_inreg node:$src, i32), [{
1836349cc55cSDimitry Andric  return hasAllWUsers(Node);
1837349cc55cSDimitry Andric}]>;
1838349cc55cSDimitry Andric
1839bdd1243dSDimitry Andricdef ImmSExt32 : SDNodeXForm<imm, [{
1840bdd1243dSDimitry Andric  return CurDAG->getTargetConstant(SignExtend64<32>(N->getSExtValue()),
1841bdd1243dSDimitry Andric                                   SDLoc(N), N->getValueType(0));
1842bdd1243dSDimitry Andric}]>;
1843bdd1243dSDimitry Andric// Look for constants where the upper 32 bits are 0, but sign extending bit 31
1844bdd1243dSDimitry Andric// would be an simm12.
1845bdd1243dSDimitry Andricdef u32simm12 : ImmLeaf<XLenVT, [{
1846bdd1243dSDimitry Andric  return isUInt<32>(Imm) && isInt<12>(SignExtend64<32>(Imm));
1847bdd1243dSDimitry Andric}], ImmSExt32>;
1848bdd1243dSDimitry Andric
18490b57cec5SDimitry Andriclet Predicates = [IsRV64] in {
18500b57cec5SDimitry Andric
1851bdd1243dSDimitry Andricdef : Pat<(i64 (and GPR:$rs, LeadingOnesWMask:$mask)),
1852*0fca6ea1SDimitry Andric          (SLLI (i64 (SRLIW $rs, LeadingOnesWMask:$mask)), LeadingOnesWMask:$mask)>;
1853bdd1243dSDimitry Andric
18540b57cec5SDimitry Andric/// sext and zext
18550b57cec5SDimitry Andric
1856349cc55cSDimitry Andric// Sign extend is not needed if all users are W instructions.
1857349cc55cSDimitry Andricdef : Pat<(sexti32_allwusers GPR:$rs1), (XLenVT GPR:$rs1)>;
1858349cc55cSDimitry Andric
18590b57cec5SDimitry Andricdef : Pat<(sext_inreg GPR:$rs1, i32), (ADDIW GPR:$rs1, 0)>;
18600b57cec5SDimitry Andric
18610b57cec5SDimitry Andric/// ALU operations
18620b57cec5SDimitry Andric
1863fe6060f1SDimitry Andricdef : Pat<(i64 (srl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)),
1864e8d8bef9SDimitry Andric          (SRLIW GPR:$rs1, uimm5:$shamt)>;
1865fe6060f1SDimitry Andricdef : Pat<(i64 (srl (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt)),
1866e8d8bef9SDimitry Andric          (SRLIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>;
18670b57cec5SDimitry Andricdef : Pat<(sra (sext_inreg GPR:$rs1, i32), uimm5:$shamt),
18680b57cec5SDimitry Andric          (SRAIW GPR:$rs1, uimm5:$shamt)>;
1869fe6060f1SDimitry Andricdef : Pat<(i64 (sra (shl GPR:$rs1, (i64 32)), uimm6gt32:$shamt)),
1870e8d8bef9SDimitry Andric          (SRAIW GPR:$rs1, (ImmSub32 uimm6gt32:$shamt))>;
18710b57cec5SDimitry Andric
1872e8d8bef9SDimitry Andricdef : PatGprGpr<shiftopw<riscv_sllw>, SLLW>;
1873e8d8bef9SDimitry Andricdef : PatGprGpr<shiftopw<riscv_srlw>, SRLW>;
1874e8d8bef9SDimitry Andricdef : PatGprGpr<shiftopw<riscv_sraw>, SRAW>;
18750b57cec5SDimitry Andric
1876349cc55cSDimitry Andric// Select W instructions if only the lower 32 bits of the result are used.
1877349cc55cSDimitry Andricdef : PatGprGpr<binop_allwusers<add>, ADDW>;
1878349cc55cSDimitry Andricdef : PatGprSimm12<binop_allwusers<add>, ADDIW>;
1879349cc55cSDimitry Andricdef : PatGprGpr<binop_allwusers<sub>, SUBW>;
1880349cc55cSDimitry Andricdef : PatGprImm<binop_allwusers<shl>, SLLIW, uimm5>;
1881349cc55cSDimitry Andric
1882349cc55cSDimitry Andric// If this is a shr of a value sign extended from i32, and all the users only
1883349cc55cSDimitry Andric// use the lower 32 bits, we can use an sraiw to remove the sext_inreg. This
1884349cc55cSDimitry Andric// occurs because SimplifyDemandedBits prefers srl over sra.
1885349cc55cSDimitry Andricdef : Pat<(binop_allwusers<srl> (sext_inreg GPR:$rs1, i32), uimm5:$shamt),
1886349cc55cSDimitry Andric          (SRAIW GPR:$rs1, uimm5:$shamt)>;
1887349cc55cSDimitry Andric
1888bdd1243dSDimitry Andric// Use binop_allwusers to recover immediates that may have been broken by
1889bdd1243dSDimitry Andric// SimplifyDemandedBits.
1890*0fca6ea1SDimitry Andricdef : Pat<(binop_allwusers<and> GPR:$rs1, 0xffffffff),
1891*0fca6ea1SDimitry Andric          (COPY GPR:$rs1)>;
1892bdd1243dSDimitry Andricdef : Pat<(binop_allwusers<and> GPR:$rs1, u32simm12:$imm),
1893bdd1243dSDimitry Andric          (ANDI GPR:$rs1, u32simm12:$imm)>;
1894bdd1243dSDimitry Andric
1895bdd1243dSDimitry Andricdef : Pat<(binop_allwusers<or> GPR:$rs1, u32simm12:$imm),
1896bdd1243dSDimitry Andric          (ORI GPR:$rs1, u32simm12:$imm)>;
1897bdd1243dSDimitry Andric
1898bdd1243dSDimitry Andricdef : Pat<(binop_allwusers<xor> GPR:$rs1, u32simm12:$imm),
1899bdd1243dSDimitry Andric          (XORI GPR:$rs1, u32simm12:$imm)>;
19000b57cec5SDimitry Andric/// Loads
19010b57cec5SDimitry Andric
190206c3fb27SDimitry Andricdef : LdPat<sextloadi32, LW, i64>;
190306c3fb27SDimitry Andricdef : LdPat<extloadi32, LW, i64>;
190406c3fb27SDimitry Andricdef : LdPat<zextloadi32, LWU, i64>;
190506c3fb27SDimitry Andricdef : LdPat<load, LD, i64>;
19060b57cec5SDimitry Andric
19070b57cec5SDimitry Andric/// Stores
19080b57cec5SDimitry Andric
190906c3fb27SDimitry Andricdef : StPat<truncstorei32, SW, GPR, i64>;
191006c3fb27SDimitry Andricdef : StPat<store, SD, GPR, i64>;
19110b57cec5SDimitry Andric} // Predicates = [IsRV64]
19120b57cec5SDimitry Andric
1913*0fca6ea1SDimitry Andric// On RV64, we can directly read these 64-bit counter CSRs.
1914*0fca6ea1SDimitry Andriclet Predicates = [IsRV64] in {
19150b57cec5SDimitry Andric/// readcyclecounter
191606c3fb27SDimitry Andricdef : Pat<(i64 (readcyclecounter)), (CSRRS CYCLE.Encoding, (XLenVT X0))>;
1917*0fca6ea1SDimitry Andric/// readsteadycounter
1918*0fca6ea1SDimitry Andricdef : Pat<(i64 (readsteadycounter)), (CSRRS TIME.Encoding, (XLenVT X0))>;
1919*0fca6ea1SDimitry Andric}
1920*0fca6ea1SDimitry Andric
1921*0fca6ea1SDimitry Andric// On RV32, ReadCounterWide will be expanded to the suggested loop reading both
1922*0fca6ea1SDimitry Andric// halves of 64-bit counter CSRs.
1923e8d8bef9SDimitry Andriclet Predicates = [IsRV32], usesCustomInserter = 1, hasNoSchedulingInfo = 1 in
1924*0fca6ea1SDimitry Andricdef ReadCounterWide : Pseudo<(outs GPR:$lo, GPR:$hi), (ins i32imm:$csr_lo, i32imm:$csr_hi),
1925*0fca6ea1SDimitry Andric                             [(set GPR:$lo, GPR:$hi,
1926*0fca6ea1SDimitry Andric                              (riscv_read_counter_wide csr_sysreg:$csr_lo, csr_sysreg:$csr_hi))],
1927e8d8bef9SDimitry Andric                             "", "">;
19280b57cec5SDimitry Andric
1929480093f4SDimitry Andric/// traps
1930480093f4SDimitry Andric
1931480093f4SDimitry Andric// We lower `trap` to `unimp`, as this causes a hard exception on nearly all
1932480093f4SDimitry Andric// systems.
1933480093f4SDimitry Andricdef : Pat<(trap), (UNIMP)>;
1934480093f4SDimitry Andric
1935480093f4SDimitry Andric// We lower `debugtrap` to `ebreak`, as this will get the attention of the
1936480093f4SDimitry Andric// debugger if possible.
1937480093f4SDimitry Andricdef : Pat<(debugtrap), (EBREAK)>;
1938480093f4SDimitry Andric
1939bdd1243dSDimitry Andriclet Predicates = [IsRV64], Uses = [X5],
1940*0fca6ea1SDimitry Andric    Defs = [X1, X6, X7, X28, X29, X30, X31], Size = 8 in
1941bdd1243dSDimitry Andricdef HWASAN_CHECK_MEMACCESS_SHORTGRANULES
1942bdd1243dSDimitry Andric  : Pseudo<(outs), (ins GPRJALR:$ptr, i32imm:$accessinfo),
19435f757f3fSDimitry Andric           [(int_hwasan_check_memaccess_shortgranules (i64 X5), GPRJALR:$ptr,
1944bdd1243dSDimitry Andric                                                      (i32 timm:$accessinfo))]>;
1945bdd1243dSDimitry Andric
194606c3fb27SDimitry Andric// This gets lowered into a 20-byte instruction sequence (at most)
194706c3fb27SDimitry Andriclet hasSideEffects = 0, mayLoad = 1, mayStore = 0,
194806c3fb27SDimitry Andric    Defs = [ X6, X7, X28, X29, X30, X31 ], Size = 20 in {
194906c3fb27SDimitry Andricdef KCFI_CHECK
195006c3fb27SDimitry Andric  : Pseudo<(outs), (ins GPRJALR:$ptr, i32imm:$type), []>, Sched<[]>;
195106c3fb27SDimitry Andric}
195206c3fb27SDimitry Andric
1953fe6060f1SDimitry Andric/// Simple optimization
195406c3fb27SDimitry Andricdef : Pat<(XLenVT (add GPR:$rs1, (AddiPair:$rs2))),
1955*0fca6ea1SDimitry Andric          (ADDI (XLenVT (ADDI GPR:$rs1, (AddiPairImmLarge AddiPair:$rs2))),
195681ad6265SDimitry Andric                (AddiPairImmSmall GPR:$rs2))>;
1957fe6060f1SDimitry Andric
1958fe6060f1SDimitry Andriclet Predicates = [IsRV64] in {
1959349cc55cSDimitry Andric// Select W instructions if only the lower 32-bits of the result are used.
1960349cc55cSDimitry Andricdef : Pat<(binop_allwusers<add> GPR:$rs1, (AddiPair:$rs2)),
1961*0fca6ea1SDimitry Andric          (ADDIW (i64 (ADDIW GPR:$rs1, (AddiPairImmLarge AddiPair:$rs2))),
196281ad6265SDimitry Andric                 (AddiPairImmSmall AddiPair:$rs2))>;
1963fe6060f1SDimitry Andric}
1964fe6060f1SDimitry Andric
19655f757f3fSDimitry Andric//===----------------------------------------------------------------------===//
19665f757f3fSDimitry Andric// Experimental RV64 i32 legalization patterns.
19675f757f3fSDimitry Andric//===----------------------------------------------------------------------===//
19685f757f3fSDimitry Andric
19695f757f3fSDimitry Andricdef simm12i32 : ImmLeaf<i32, [{return isInt<12>(Imm);}]>;
19705f757f3fSDimitry Andric
19715f757f3fSDimitry Andric// Convert from i32 immediate to i64 target immediate to make SelectionDAG type
19725f757f3fSDimitry Andric// checking happy so we can use ADDIW which expects an XLen immediate.
19735f757f3fSDimitry Andricdef as_i64imm : SDNodeXForm<imm, [{
19745f757f3fSDimitry Andric  return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i64);
19755f757f3fSDimitry Andric}]>;
19765f757f3fSDimitry Andric
19775f757f3fSDimitry Andricdef zext_is_sext : PatFrag<(ops node:$src), (zext node:$src), [{
19785f757f3fSDimitry Andric  KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0), 0);
19795f757f3fSDimitry Andric  return Known.isNonNegative();
19805f757f3fSDimitry Andric}]>;
19815f757f3fSDimitry Andric
19825f757f3fSDimitry Andriclet Predicates = [IsRV64] in {
19835f757f3fSDimitry Andricdef : LdPat<sextloadi8, LB, i32>;
19845f757f3fSDimitry Andricdef : LdPat<extloadi8, LBU, i32>; // Prefer unsigned due to no c.lb in Zcb.
19855f757f3fSDimitry Andricdef : LdPat<sextloadi16, LH, i32>;
19865f757f3fSDimitry Andricdef : LdPat<extloadi16, LH, i32>;
19875f757f3fSDimitry Andricdef : LdPat<zextloadi8, LBU, i32>;
19885f757f3fSDimitry Andricdef : LdPat<zextloadi16, LHU, i32>;
19895f757f3fSDimitry Andric
19905f757f3fSDimitry Andricdef : StPat<truncstorei8, SB, GPR, i32>;
19915f757f3fSDimitry Andricdef : StPat<truncstorei16, SH, GPR, i32>;
19925f757f3fSDimitry Andric
19935f757f3fSDimitry Andricdef : Pat<(anyext GPR:$src), (COPY GPR:$src)>;
19945f757f3fSDimitry Andricdef : Pat<(sext GPR:$src), (ADDIW GPR:$src, 0)>;
19955f757f3fSDimitry Andricdef : Pat<(trunc GPR:$src), (COPY GPR:$src)>;
19965f757f3fSDimitry Andric
19975f757f3fSDimitry Andricdef : PatGprGpr<add, ADDW, i32, i32>;
19985f757f3fSDimitry Andricdef : PatGprGpr<sub, SUBW, i32, i32>;
19995f757f3fSDimitry Andricdef : PatGprGpr<and, AND, i32, i32>;
20005f757f3fSDimitry Andricdef : PatGprGpr<or, OR, i32, i32>;
20015f757f3fSDimitry Andricdef : PatGprGpr<xor, XOR, i32, i32>;
20025f757f3fSDimitry Andricdef : PatGprGpr<shiftopw<shl>, SLLW, i32, i64>;
20035f757f3fSDimitry Andricdef : PatGprGpr<shiftopw<srl>, SRLW, i32, i64>;
20045f757f3fSDimitry Andricdef : PatGprGpr<shiftopw<sra>, SRAW, i32, i64>;
20055f757f3fSDimitry Andric
20065f757f3fSDimitry Andricdef : Pat<(i32 (add GPR:$rs1, simm12i32:$imm)),
20075f757f3fSDimitry Andric          (ADDIW GPR:$rs1, (i64 (as_i64imm $imm)))>;
20085f757f3fSDimitry Andricdef : Pat<(i32 (and GPR:$rs1, simm12i32:$imm)),
20095f757f3fSDimitry Andric          (ANDI GPR:$rs1, (i64 (as_i64imm $imm)))>;
20105f757f3fSDimitry Andricdef : Pat<(i32 (or GPR:$rs1, simm12i32:$imm)),
20115f757f3fSDimitry Andric          (ORI GPR:$rs1, (i64 (as_i64imm $imm)))>;
20125f757f3fSDimitry Andricdef : Pat<(i32 (xor GPR:$rs1, simm12i32:$imm)),
20135f757f3fSDimitry Andric          (XORI GPR:$rs1, (i64 (as_i64imm $imm)))>;
20145f757f3fSDimitry Andric
20155f757f3fSDimitry Andricdef : PatGprImm<shl, SLLIW, uimm5, i32>;
20165f757f3fSDimitry Andricdef : PatGprImm<srl, SRLIW, uimm5, i32>;
20175f757f3fSDimitry Andricdef : PatGprImm<sra, SRAIW, uimm5, i32>;
20185f757f3fSDimitry Andric
20195f757f3fSDimitry Andricdef : Pat<(i32 (and GPR:$rs, TrailingOnesMask:$mask)),
2020*0fca6ea1SDimitry Andric          (SRLI (i32 (SLLI $rs, (i64 (XLenSubTrailingOnes $mask)))),
20215f757f3fSDimitry Andric                (i64 (XLenSubTrailingOnes $mask)))>;
20225f757f3fSDimitry Andric
20235f757f3fSDimitry Andric// Use sext if the sign bit of the input is 0.
20245f757f3fSDimitry Andricdef : Pat<(zext_is_sext GPR:$src), (ADDIW GPR:$src, 0)>;
20255f757f3fSDimitry Andric}
20265f757f3fSDimitry Andric
20275f757f3fSDimitry Andriclet Predicates = [IsRV64, NotHasStdExtZba] in {
2028*0fca6ea1SDimitry Andricdef : Pat<(zext GPR:$src), (SRLI (i64 (SLLI GPR:$src, 32)), 32)>;
20295f757f3fSDimitry Andric
20305f757f3fSDimitry Andric// If we're shifting a 32-bit zero extended value left by 0-31 bits, use 2
20315f757f3fSDimitry Andric// shifts instead of 3. This can occur when unsigned is used to index an array.
20325f757f3fSDimitry Andricdef : Pat<(shl (zext GPR:$rs), uimm5:$shamt),
2033*0fca6ea1SDimitry Andric          (SRLI (i64 (SLLI GPR:$rs, 32)), (ImmSubFrom32 uimm5:$shamt))>;
20345f757f3fSDimitry Andric}
20355f757f3fSDimitry Andric
20360b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
20370b57cec5SDimitry Andric// Standard extensions
20380b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
20390b57cec5SDimitry Andric
204006c3fb27SDimitry Andric// Multiply and Division
20410b57cec5SDimitry Andricinclude "RISCVInstrInfoM.td"
204206c3fb27SDimitry Andric
204306c3fb27SDimitry Andric// Atomic
20440b57cec5SDimitry Andricinclude "RISCVInstrInfoA.td"
20451db9f3b2SDimitry Andricinclude "RISCVInstrInfoZa.td"
2046*0fca6ea1SDimitry Andricinclude "RISCVInstrInfoZalasr.td"
204706c3fb27SDimitry Andric
204806c3fb27SDimitry Andric// Scalar FP
20490b57cec5SDimitry Andricinclude "RISCVInstrInfoF.td"
20500b57cec5SDimitry Andricinclude "RISCVInstrInfoD.td"
205106c3fb27SDimitry Andricinclude "RISCVInstrInfoZfh.td"
205206c3fb27SDimitry Andricinclude "RISCVInstrInfoZfbfmin.td"
205306c3fb27SDimitry Andricinclude "RISCVInstrInfoZfa.td"
205406c3fb27SDimitry Andric
205506c3fb27SDimitry Andric// Scalar bitmanip and cryptography
2056349cc55cSDimitry Andricinclude "RISCVInstrInfoZb.td"
205704eeddc0SDimitry Andricinclude "RISCVInstrInfoZk.td"
205806c3fb27SDimitry Andric
205906c3fb27SDimitry Andric// Vector
20605ffd83dbSDimitry Andricinclude "RISCVInstrInfoV.td"
206106c3fb27SDimitry Andricinclude "RISCVInstrInfoZvk.td"
206206c3fb27SDimitry Andric
206306c3fb27SDimitry Andric// Compressed
206406c3fb27SDimitry Andricinclude "RISCVInstrInfoC.td"
206506c3fb27SDimitry Andricinclude "RISCVInstrInfoZc.td"
2066647cbc5dSDimitry Andricinclude "RISCVInstrInfoZcmop.td"
2067647cbc5dSDimitry Andric
2068647cbc5dSDimitry Andric// Integer
2069647cbc5dSDimitry Andricinclude "RISCVInstrInfoZimop.td"
2070647cbc5dSDimitry Andricinclude "RISCVInstrInfoZicbo.td"
2071647cbc5dSDimitry Andricinclude "RISCVInstrInfoZicond.td"
2072647cbc5dSDimitry Andricinclude "RISCVInstrInfoZicfiss.td"
2073bdd1243dSDimitry Andric
2074bdd1243dSDimitry Andric//===----------------------------------------------------------------------===//
2075bdd1243dSDimitry Andric// Vendor extensions
2076bdd1243dSDimitry Andric//===----------------------------------------------------------------------===//
2077bdd1243dSDimitry Andric
2078bdd1243dSDimitry Andricinclude "RISCVInstrInfoXVentana.td"
2079bdd1243dSDimitry Andricinclude "RISCVInstrInfoXTHead.td"
208006c3fb27SDimitry Andricinclude "RISCVInstrInfoXSf.td"
2081*0fca6ea1SDimitry Andricinclude "RISCVInstrInfoSFB.td"
208206c3fb27SDimitry Andricinclude "RISCVInstrInfoXCV.td"
2083*0fca6ea1SDimitry Andricinclude "RISCVInstrInfoXwch.td"
20845f757f3fSDimitry Andric
20855f757f3fSDimitry Andric//===----------------------------------------------------------------------===//
20865f757f3fSDimitry Andric// Global ISel
20875f757f3fSDimitry Andric//===----------------------------------------------------------------------===//
20885f757f3fSDimitry Andric
20895f757f3fSDimitry Andricinclude "RISCVInstrGISel.td"
2090