xref: /llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td (revision 6e7312bda60249c25e2ae9078d9f70bc2a65838c)
1//===-- RISCVInstrInfoZb.td - RISC-V Bitmanip instructions -*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file describes the RISC-V instructions from the standard Bitmanip
10// extensions, versions:
11//   Zba - 1.0
12//   Zbb - 1.0
13//   Zbc - 1.0
14//   Zbs - 1.0
15//
16// This file also describes RISC-V instructions from the Zbk* extensions in
17// Cryptography Extensions Volume I: Scalar & Entropy Source Instructions,
18// versions:
19//   Zbkb - 1.0
20//   Zbkc - 1.0
21//   Zbkx - 1.0
22//
23//===----------------------------------------------------------------------===//
24
25//===----------------------------------------------------------------------===//
26// Operand and SDNode transformation definitions.
27//===----------------------------------------------------------------------===//
28
29def SDTIntShiftAddOp : SDTypeProfile<1, 3, [   // shl_add
30  SDTCisSameAs<0, 1>, SDTCisSameAs<0, 3>, SDTCisInt<0>, SDTCisInt<2>,
31  SDTCisInt<3>
32]>;
33
34def riscv_shl_add : SDNode<"RISCVISD::SHL_ADD", SDTIntShiftAddOp>;
35def riscv_clzw    : SDNode<"RISCVISD::CLZW",    SDT_RISCVIntUnaryOpW>;
36def riscv_ctzw    : SDNode<"RISCVISD::CTZW",    SDT_RISCVIntUnaryOpW>;
37def riscv_rolw    : SDNode<"RISCVISD::ROLW",    SDT_RISCVIntBinOpW>;
38def riscv_rorw    : SDNode<"RISCVISD::RORW",    SDT_RISCVIntBinOpW>;
39def riscv_brev8   : SDNode<"RISCVISD::BREV8",   SDTIntUnaryOp>;
40def riscv_orc_b   : SDNode<"RISCVISD::ORC_B",   SDTIntUnaryOp>;
41def riscv_zip     : SDNode<"RISCVISD::ZIP",     SDTIntUnaryOp>;
42def riscv_unzip   : SDNode<"RISCVISD::UNZIP",   SDTIntUnaryOp>;
43def riscv_absw    : SDNode<"RISCVISD::ABSW",    SDTIntUnaryOp>;
44def riscv_clmul   : SDNode<"RISCVISD::CLMUL",   SDTIntBinOp>;
45def riscv_clmulh  : SDNode<"RISCVISD::CLMULH",  SDTIntBinOp>;
46def riscv_clmulr  : SDNode<"RISCVISD::CLMULR",  SDTIntBinOp>;
47
48def BCLRXForm : SDNodeXForm<imm, [{
49  // Find the lowest 0.
50  return CurDAG->getTargetConstant(llvm::countr_one(N->getZExtValue()),
51                                   SDLoc(N), N->getValueType(0));
52}]>;
53
54def SingleBitSetMaskToIndex : SDNodeXForm<imm, [{
55  // Find the lowest 1.
56  return CurDAG->getTargetConstant(llvm::countr_zero(N->getZExtValue()),
57                                   SDLoc(N), N->getValueType(0));
58}]>;
59
60// Checks if this mask has a single 0 bit and cannot be used with ANDI.
61def BCLRMask : ImmLeaf<XLenVT, [{
62  if (Subtarget->is64Bit())
63    return !isInt<12>(Imm) && isPowerOf2_64(~Imm);
64  return !isInt<12>(Imm) && isPowerOf2_32(~Imm);
65}], BCLRXForm>;
66
67// Checks if this mask has a single 1 bit and cannot be used with ORI/XORI.
68def SingleBitSetMask : ImmLeaf<XLenVT, [{
69  if (Subtarget->is64Bit())
70    return !isInt<12>(Imm) && isPowerOf2_64(Imm);
71  return !isInt<12>(Imm) && isPowerOf2_32(Imm);
72}], SingleBitSetMaskToIndex>;
73
74// Check if (or r, i) can be optimized to (BSETI (BSETI r, i0), i1),
75// in which i = (1 << i0) | (1 << i1).
76def BSETINVTwoBitsMask : PatLeaf<(imm), [{
77  if (!N->hasOneUse())
78    return false;
79  // The immediate should not be a simm12.
80  if (isInt<12>(N->getSExtValue()))
81    return false;
82  // The immediate must have exactly two bits set.
83  return llvm::popcount(N->getZExtValue()) == 2;
84}]>;
85
86def BSETINVTwoBitsMaskHigh : SDNodeXForm<imm, [{
87  uint64_t I = N->getZExtValue();
88  return CurDAG->getTargetConstant(llvm::Log2_64(I), SDLoc(N),
89                                   N->getValueType(0));
90}]>;
91
92// Check if (or r, imm) can be optimized to (BSETI (ORI r, i0), i1),
93// in which imm = i0 | (1 << i1).
94def BSETINVORIMask : PatLeaf<(imm), [{
95  if (!N->hasOneUse())
96    return false;
97  // The immediate should not be a simm12.
98  if (isInt<12>(N->getSExtValue()))
99    return false;
100  // There should be only one set bit from bit 11 to the top.
101  return isPowerOf2_64(N->getZExtValue() & ~0x7ff);
102}]>;
103
104def BSETINVORIMaskLow : SDNodeXForm<imm, [{
105  return CurDAG->getTargetConstant(N->getZExtValue() & 0x7ff,
106                                   SDLoc(N), N->getValueType(0));
107}]>;
108
109// Check if (and r, i) can be optimized to (BCLRI (BCLRI r, i0), i1),
110// in which i = ~((1<<i0) | (1<<i1)).
111def BCLRITwoBitsMask : PatLeaf<(imm), [{
112  if (!N->hasOneUse())
113    return false;
114  // The immediate should not be a simm12.
115  if (isInt<12>(N->getSExtValue()))
116    return false;
117  // The immediate must have exactly two bits clear.
118  return (unsigned)llvm::popcount(N->getZExtValue()) == Subtarget->getXLen() - 2;
119}]>;
120
121def BCLRITwoBitsMaskLow : SDNodeXForm<imm, [{
122  return CurDAG->getTargetConstant(llvm::countr_zero(~N->getZExtValue()),
123                                   SDLoc(N), N->getValueType(0));
124}]>;
125
126def BCLRITwoBitsMaskHigh : SDNodeXForm<imm, [{
127  uint64_t I = N->getZExtValue();
128  if (!Subtarget->is64Bit())
129    I |= maskLeadingOnes<uint64_t>(32);
130  return CurDAG->getTargetConstant(llvm::Log2_64(~I), SDLoc(N),
131                                   N->getValueType(0));
132}]>;
133
134// Check if (and r, i) can be optimized to (BCLRI (ANDI r, i0), i1),
135// in which i = i0 & ~(1<<i1).
136def BCLRIANDIMask : PatLeaf<(imm), [{
137  if (!N->hasOneUse())
138    return false;
139  // The immediate should not be a simm12.
140  if (isInt<12>(N->getSExtValue()))
141    return false;
142  // There should be only one clear bit from bit 11 to the top.
143  uint64_t I = N->getZExtValue() | 0x7ff;
144  return Subtarget->is64Bit() ? isPowerOf2_64(~I) : isPowerOf2_32(~I);
145}]>;
146
147def BCLRIANDIMaskLow : SDNodeXForm<imm, [{
148  return CurDAG->getSignedTargetConstant((N->getZExtValue() & 0x7ff) | ~0x7ffull,
149                                         SDLoc(N), N->getValueType(0));
150}]>;
151
152def SimmShiftRightBy2XForm : SDNodeXForm<imm, [{
153  return CurDAG->getSignedTargetConstant(N->getSExtValue() >> 2, SDLoc(N),
154                                         N->getValueType(0));
155}]>;
156
157def SimmShiftRightBy3XForm : SDNodeXForm<imm, [{
158  return CurDAG->getSignedTargetConstant(N->getSExtValue() >> 3, SDLoc(N),
159                                         N->getValueType(0));
160}]>;
161
162def CSImm12MulBy4 : PatLeaf<(imm), [{
163  if (!N->hasOneUse())
164    return false;
165  int64_t C = N->getSExtValue();
166  // Skip if C is simm12, an lui, or can be optimized by the PatLeaf AddiPair.
167  return !isInt<13>(C) && !isShiftedInt<20, 12>(C) && isShiftedInt<12, 2>(C);
168}], SimmShiftRightBy2XForm>;
169
170def CSImm12MulBy8 : PatLeaf<(imm), [{
171  if (!N->hasOneUse())
172    return false;
173  int64_t C = N->getSExtValue();
174  // Skip if C is simm12, an lui or can be optimized by the PatLeaf AddiPair or
175  // CSImm12MulBy4.
176  return !isInt<14>(C) && !isShiftedInt<20, 12>(C) && isShiftedInt<12, 3>(C);
177}], SimmShiftRightBy3XForm>;
178
179// Pattern to exclude simm12 immediates from matching, namely `non_imm12`.
180// GISel currently doesn't support PatFrag for leaf nodes, so `non_imm12`
181// cannot be implemented in that way. To reuse patterns between the two
182// ISels, we instead create PatFrag on operators that use `non_imm12`.
183class binop_with_non_imm12<SDPatternOperator binop>
184  : PatFrag<(ops node:$x, node:$y), (binop node:$x, node:$y), [{
185  auto *C = dyn_cast<ConstantSDNode>(Operands[1]);
186  return !C || !isInt<12>(C->getSExtValue());
187}]> {
188  let PredicateCodeUsesOperands = 1;
189  let GISelPredicateCode = [{
190    const MachineOperand &ImmOp = *Operands[1];
191
192    if (ImmOp.isReg() && ImmOp.getReg())
193      if (auto Val = getIConstantVRegValWithLookThrough(ImmOp.getReg(), MRI)) {
194        // We do NOT want immediates that fit in 12 bits.
195        return !isInt<12>(Val->Value.getSExtValue());
196      }
197
198    return true;
199  }];
200}
201def add_non_imm12       : binop_with_non_imm12<add>;
202def add_like_non_imm12 : binop_with_non_imm12<add_like>;
203
204def Shifted32OnesMask : IntImmLeaf<XLenVT, [{
205  if (!Imm.isShiftedMask())
206    return false;
207
208  unsigned TrailingZeros = Imm.countr_zero();
209  return TrailingZeros > 0 && TrailingZeros < 32 &&
210         Imm == UINT64_C(0xFFFFFFFF) << TrailingZeros;
211}], TrailingZeros>;
212
213def sh1add_op : ComplexPattern<XLenVT, 1, "selectSHXADDOp<1>", [], [], 6>;
214def sh2add_op : ComplexPattern<XLenVT, 1, "selectSHXADDOp<2>", [], [], 6>;
215def sh3add_op : ComplexPattern<XLenVT, 1, "selectSHXADDOp<3>", [], [], 6>;
216def gi_sh1add_op : GIComplexOperandMatcher<s32, "selectSHXADDOp<1>">,
217                   GIComplexPatternEquiv<sh1add_op>;
218def gi_sh2add_op : GIComplexOperandMatcher<s32, "selectSHXADDOp<2>">,
219                   GIComplexPatternEquiv<sh2add_op>;
220def gi_sh3add_op : GIComplexOperandMatcher<s32, "selectSHXADDOp<3>">,
221                   GIComplexPatternEquiv<sh3add_op>;
222
223
224def sh1add_uw_op : ComplexPattern<XLenVT, 1, "selectSHXADD_UWOp<1>", [], [], 6>;
225def sh2add_uw_op : ComplexPattern<XLenVT, 1, "selectSHXADD_UWOp<2>", [], [], 6>;
226def sh3add_uw_op : ComplexPattern<XLenVT, 1, "selectSHXADD_UWOp<3>", [], [], 6>;
227def gi_sh1add_uw_op : GIComplexOperandMatcher<s32, "selectSHXADD_UWOp<1>">,
228                      GIComplexPatternEquiv<sh1add_uw_op>;
229def gi_sh2add_uw_op : GIComplexOperandMatcher<s32, "selectSHXADD_UWOp<2>">,
230                      GIComplexPatternEquiv<sh2add_uw_op>;
231def gi_sh3add_uw_op : GIComplexOperandMatcher<s32, "selectSHXADD_UWOp<3>">,
232                      GIComplexPatternEquiv<sh3add_uw_op>;
233
234//===----------------------------------------------------------------------===//
235// Instruction class templates
236//===----------------------------------------------------------------------===//
237
238let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
239class RVBUnaryR<bits<7> funct7, bits<3> funct3,
240                RISCVOpcode opcode, string opcodestr>
241    : RVInstR<funct7, funct3, opcode, (outs GPR:$rd), (ins GPR:$rs1),
242              opcodestr, "$rd, $rs1"> {
243  let rs2 = 0;
244}
245
246let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
247class RVBShift_ri<bits<5> imm11_7, bits<3> funct3, RISCVOpcode opcode,
248                  string opcodestr>
249    : RVInstIShift<imm11_7, funct3, opcode, (outs GPR:$rd),
250                   (ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr,
251                   "$rd, $rs1, $shamt">;
252
253//===----------------------------------------------------------------------===//
254// Instructions
255//===----------------------------------------------------------------------===//
256
257let Predicates = [HasStdExtZbbOrZbkb] in {
258def ANDN  : ALU_rr<0b0100000, 0b111, "andn">,
259            Sched<[WriteIALU, ReadIALU, ReadIALU]>;
260def ORN   : ALU_rr<0b0100000, 0b110, "orn">,
261            Sched<[WriteIALU, ReadIALU, ReadIALU]>;
262def XNOR  : ALU_rr<0b0100000, 0b100, "xnor">,
263            Sched<[WriteIALU, ReadIALU, ReadIALU]>;
264} // Predicates = [HasStdExtZbbOrZbkb]
265
266let Predicates = [HasStdExtZba] in {
267def SH1ADD : ALU_rr<0b0010000, 0b010, "sh1add">,
268             Sched<[WriteSHXADD, ReadSHXADD, ReadSHXADD]>;
269def SH2ADD : ALU_rr<0b0010000, 0b100, "sh2add">,
270             Sched<[WriteSHXADD, ReadSHXADD, ReadSHXADD]>;
271def SH3ADD : ALU_rr<0b0010000, 0b110, "sh3add">,
272             Sched<[WriteSHXADD, ReadSHXADD, ReadSHXADD]>;
273} // Predicates = [HasStdExtZba]
274
275let Predicates = [HasStdExtZba, IsRV64] in {
276def SLLI_UW : RVBShift_ri<0b00001, 0b001, OPC_OP_IMM_32, "slli.uw">,
277              Sched<[WriteShiftImm32, ReadShiftImm32]>;
278def ADD_UW : ALUW_rr<0b0000100, 0b000, "add.uw">,
279             Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;
280def SH1ADD_UW : ALUW_rr<0b0010000, 0b010, "sh1add.uw">,
281                Sched<[WriteSHXADD32, ReadSHXADD32, ReadSHXADD32]>;
282def SH2ADD_UW : ALUW_rr<0b0010000, 0b100, "sh2add.uw">,
283                Sched<[WriteSHXADD32, ReadSHXADD32, ReadSHXADD32]>;
284def SH3ADD_UW : ALUW_rr<0b0010000, 0b110, "sh3add.uw">,
285                Sched<[WriteSHXADD32, ReadSHXADD32, ReadSHXADD32]>;
286} // Predicates = [HasStdExtZba, IsRV64]
287
288let Predicates = [HasStdExtZbbOrZbkb] in {
289def ROL   : ALU_rr<0b0110000, 0b001, "rol">,
290            Sched<[WriteRotateReg, ReadRotateReg, ReadRotateReg]>;
291def ROR   : ALU_rr<0b0110000, 0b101, "ror">,
292            Sched<[WriteRotateReg, ReadRotateReg, ReadRotateReg]>;
293
294def RORI  : Shift_ri<0b01100, 0b101, "rori">,
295            Sched<[WriteRotateImm, ReadRotateImm]>;
296} // Predicates = [HasStdExtZbbOrZbkb]
297
298let Predicates = [HasStdExtZbbOrZbkb, IsRV64], IsSignExtendingOpW = 1 in {
299def ROLW  : ALUW_rr<0b0110000, 0b001, "rolw">,
300            Sched<[WriteRotateReg32, ReadRotateReg32, ReadRotateReg32]>;
301def RORW  : ALUW_rr<0b0110000, 0b101, "rorw">,
302            Sched<[WriteRotateReg32, ReadRotateReg32, ReadRotateReg32]>;
303
304def RORIW : ShiftW_ri<0b0110000, 0b101, "roriw">,
305            Sched<[WriteRotateImm32, ReadRotateImm32]>;
306} // Predicates = [HasStdExtZbbOrZbkb, IsRV64]
307
308let Predicates = [HasStdExtZbs] in {
309def BCLR : ALU_rr<0b0100100, 0b001, "bclr">,
310           Sched<[WriteSingleBit, ReadSingleBit, ReadSingleBit]>;
311def BSET : ALU_rr<0b0010100, 0b001, "bset">,
312           Sched<[WriteSingleBit, ReadSingleBit, ReadSingleBit]>;
313def BINV : ALU_rr<0b0110100, 0b001, "binv">,
314           Sched<[WriteSingleBit, ReadSingleBit, ReadSingleBit]>;
315let IsSignExtendingOpW = 1 in
316def BEXT : ALU_rr<0b0100100, 0b101, "bext">,
317           Sched<[WriteBEXT, ReadSingleBit, ReadSingleBit]>;
318
319def BCLRI : Shift_ri<0b01001, 0b001, "bclri">,
320            Sched<[WriteSingleBitImm, ReadSingleBitImm]>;
321def BSETI : Shift_ri<0b00101, 0b001, "bseti">,
322            Sched<[WriteSingleBitImm, ReadSingleBitImm]>;
323def BINVI : Shift_ri<0b01101, 0b001, "binvi">,
324            Sched<[WriteSingleBitImm, ReadSingleBitImm]>;
325let IsSignExtendingOpW = 1 in
326def BEXTI : Shift_ri<0b01001, 0b101, "bexti">,
327            Sched<[WriteBEXTI, ReadSingleBitImm]>;
328} // Predicates = [HasStdExtZbs]
329
330// These instructions were named xperm.n and xperm.b in the last version of
331// the draft bit manipulation specification they were included in. However, we
332// use the mnemonics given to them in the ratified Zbkx extension.
333let Predicates = [HasStdExtZbkx] in {
334def XPERM4 : ALU_rr<0b0010100, 0b010, "xperm4">,
335             Sched<[WriteXPERM, ReadXPERM, ReadXPERM]>;
336def XPERM8 : ALU_rr<0b0010100, 0b100, "xperm8">,
337             Sched<[WriteXPERM, ReadXPERM, ReadXPERM]>;
338} // Predicates = [HasStdExtZbkx]
339
340let Predicates = [HasStdExtZbb], IsSignExtendingOpW = 1 in {
341def CLZ  : Unary_r<0b011000000000, 0b001, "clz">,
342           Sched<[WriteCLZ, ReadCLZ]>;
343def CTZ  : Unary_r<0b011000000001, 0b001, "ctz">,
344           Sched<[WriteCTZ, ReadCTZ]>;
345def CPOP : Unary_r<0b011000000010, 0b001, "cpop">,
346           Sched<[WriteCPOP, ReadCPOP]>;
347} // Predicates = [HasStdExtZbb]
348
349let Predicates = [HasStdExtZbb, IsRV64], IsSignExtendingOpW = 1 in {
350def CLZW  : UnaryW_r<0b011000000000, 0b001, "clzw">,
351            Sched<[WriteCLZ32, ReadCLZ32]>;
352def CTZW  : UnaryW_r<0b011000000001, 0b001, "ctzw">,
353            Sched<[WriteCTZ32, ReadCTZ32]>;
354def CPOPW : UnaryW_r<0b011000000010, 0b001, "cpopw">,
355            Sched<[WriteCPOP32, ReadCPOP32]>;
356} // Predicates = [HasStdExtZbb, IsRV64]
357
358let Predicates = [HasStdExtZbb], IsSignExtendingOpW = 1 in {
359def SEXT_B : Unary_r<0b011000000100, 0b001, "sext.b">,
360             Sched<[WriteIALU, ReadIALU]>;
361def SEXT_H : Unary_r<0b011000000101, 0b001, "sext.h">,
362             Sched<[WriteIALU, ReadIALU]>;
363} // Predicates = [HasStdExtZbb]
364
365let Predicates = [HasStdExtZbc] in {
366def CLMULR : ALU_rr<0b0000101, 0b010, "clmulr", Commutable=1>,
367             Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>;
368} // Predicates = [HasStdExtZbc]
369
370let Predicates = [HasStdExtZbcOrZbkc] in {
371def CLMUL  : ALU_rr<0b0000101, 0b001, "clmul", Commutable=1>,
372             Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>;
373def CLMULH : ALU_rr<0b0000101, 0b011, "clmulh", Commutable=1>,
374             Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>;
375} // Predicates = [HasStdExtZbcOrZbkc]
376
377let Predicates = [HasStdExtZbb] in {
378def MIN  : ALU_rr<0b0000101, 0b100, "min", Commutable=1>,
379           Sched<[WriteIMinMax, ReadIMinMax, ReadIMinMax]>;
380def MINU : ALU_rr<0b0000101, 0b101, "minu", Commutable=1>,
381           Sched<[WriteIMinMax, ReadIMinMax, ReadIMinMax]>;
382def MAX  : ALU_rr<0b0000101, 0b110, "max", Commutable=1>,
383           Sched<[WriteIMinMax, ReadIMinMax, ReadIMinMax]>;
384def MAXU : ALU_rr<0b0000101, 0b111, "maxu", Commutable=1>,
385           Sched<[WriteIMinMax, ReadIMinMax, ReadIMinMax]>;
386} // Predicates = [HasStdExtZbb]
387
388let Predicates = [HasStdExtZbkb] in {
389def PACK  : ALU_rr<0b0000100, 0b100, "pack">,
390            Sched<[WritePACK, ReadPACK, ReadPACK]>;
391let IsSignExtendingOpW = 1 in
392def PACKH : ALU_rr<0b0000100, 0b111, "packh">,
393            Sched<[WritePACK, ReadPACK, ReadPACK]>;
394} // Predicates = [HasStdExtZbkb]
395
396let Predicates = [HasStdExtZbkb, IsRV64], IsSignExtendingOpW = 1 in
397def PACKW  : ALUW_rr<0b0000100, 0b100, "packw">,
398             Sched<[WritePACK32, ReadPACK32, ReadPACK32]>;
399
400let Predicates = [HasStdExtZbb, IsRV32] in {
401def ZEXT_H_RV32 : RVBUnaryR<0b0000100, 0b100, OPC_OP, "zext.h">,
402                  Sched<[WriteIALU, ReadIALU]>;
403} // Predicates = [HasStdExtZbb, IsRV32]
404
405let Predicates = [HasStdExtZbb, IsRV64], IsSignExtendingOpW = 1 in {
406def ZEXT_H_RV64 : RVBUnaryR<0b0000100, 0b100, OPC_OP_32, "zext.h">,
407                  Sched<[WriteIALU, ReadIALU]>;
408} // Predicates = [HasStdExtZbb, IsRV64]
409
410let Predicates = [HasStdExtZbbOrZbkb, IsRV32] in {
411def REV8_RV32 : Unary_r<0b011010011000, 0b101, "rev8">,
412                Sched<[WriteREV8, ReadREV8]>;
413} // Predicates = [HasStdExtZbbOrZbkb, IsRV32]
414
415let Predicates = [HasStdExtZbbOrZbkb, IsRV64] in {
416def REV8_RV64 : Unary_r<0b011010111000, 0b101, "rev8">,
417                Sched<[WriteREV8, ReadREV8]>;
418} // Predicates = [HasStdExtZbbOrZbkb, IsRV64]
419
420let Predicates = [HasStdExtZbb] in {
421def ORC_B : Unary_r<0b001010000111, 0b101, "orc.b">,
422            Sched<[WriteORCB, ReadORCB]>;
423} // Predicates = [HasStdExtZbb]
424
425let Predicates = [HasStdExtZbkb] in
426def BREV8 : Unary_r<0b011010000111, 0b101, "brev8">,
427            Sched<[WriteBREV8, ReadBREV8]>;
428
429let Predicates = [HasStdExtZbkb, IsRV32] in {
430def ZIP_RV32   : Unary_r<0b000010001111, 0b001, "zip">,
431                 Sched<[WriteZIP, ReadZIP]>;
432def UNZIP_RV32 : Unary_r<0b000010001111, 0b101, "unzip">,
433                 Sched<[WriteZIP, ReadZIP]>;
434} // Predicates = [HasStdExtZbkb, IsRV32]
435
436
437//===----------------------------------------------------------------------===//
438// Pseudo Instructions
439//===----------------------------------------------------------------------===//
440
441let Predicates = [HasStdExtZba, IsRV64] in {
442def : InstAlias<"zext.w $rd, $rs", (ADD_UW GPR:$rd, GPR:$rs, X0)>;
443} // Predicates = [HasStdExtZba, IsRV64]
444
445let Predicates = [HasStdExtZbb] in {
446def : InstAlias<"ror $rd, $rs1, $shamt",
447                (RORI  GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>;
448} // Predicates = [HasStdExtZbb]
449
450let Predicates = [HasStdExtZbb, IsRV64] in {
451def : InstAlias<"rorw $rd, $rs1, $shamt",
452                (RORIW  GPR:$rd, GPR:$rs1, uimm5:$shamt), 0>;
453} // Predicates = [HasStdExtZbb, IsRV64]
454
455let Predicates = [HasStdExtZbs] in {
456def : InstAlias<"bset $rd, $rs1, $shamt",
457                (BSETI  GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>;
458def : InstAlias<"bclr $rd, $rs1, $shamt",
459                (BCLRI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>;
460def : InstAlias<"binv $rd, $rs1, $shamt",
461                (BINVI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>;
462def : InstAlias<"bext $rd, $rs1, $shamt",
463                (BEXTI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>;
464} // Predicates = [HasStdExtZbs]
465
466let Predicates = [HasStdExtZbkb, NoStdExtZbb, IsRV32] in {
467def : InstAlias<"zext.h $rd, $rs", (PACK GPR:$rd, GPR:$rs, X0)>;
468} // Predicates = [HasStdExtZbkb, NoStdExtZbb, IsRV32]
469
470let Predicates = [HasStdExtZbkb, NoStdExtZbb, IsRV64] in {
471def : InstAlias<"zext.h $rd, $rs", (PACKW GPR:$rd, GPR:$rs, X0)>;
472} // Predicates = [HasStdExtZbkb, NoStdExtZbb, IsRV64]
473
474//===----------------------------------------------------------------------===//
475// Codegen patterns
476//===----------------------------------------------------------------------===//
477
478def invLogicImm : ComplexPattern<XLenVT, 1, "selectInvLogicImm", [], [], 0>;
479
480let Predicates = [HasStdExtZbbOrZbkb] in {
481def : Pat<(XLenVT (and GPR:$rs1, (not GPR:$rs2))), (ANDN GPR:$rs1, GPR:$rs2)>;
482def : Pat<(XLenVT (or  GPR:$rs1, (not GPR:$rs2))), (ORN  GPR:$rs1, GPR:$rs2)>;
483def : Pat<(XLenVT (xor GPR:$rs1, (not GPR:$rs2))), (XNOR GPR:$rs1, GPR:$rs2)>;
484
485def : Pat<(XLenVT (and GPR:$rs1, invLogicImm:$rs2)), (ANDN GPR:$rs1, invLogicImm:$rs2)>;
486def : Pat<(XLenVT (or  GPR:$rs1, invLogicImm:$rs2)), (ORN  GPR:$rs1, invLogicImm:$rs2)>;
487def : Pat<(XLenVT (xor GPR:$rs1, invLogicImm:$rs2)), (XNOR GPR:$rs1, invLogicImm:$rs2)>;
488} // Predicates = [HasStdExtZbbOrZbkb]
489
490let Predicates = [HasStdExtZbbOrZbkb] in {
491def : PatGprGpr<shiftop<rotl>, ROL>;
492def : PatGprGpr<shiftop<rotr>, ROR>;
493
494def : PatGprImm<rotr, RORI, uimmlog2xlen>;
495// There's no encoding for roli in the the 'B' extension as it can be
496// implemented with rori by negating the immediate.
497def : Pat<(XLenVT (rotl GPR:$rs1, uimmlog2xlen:$shamt)),
498          (RORI GPR:$rs1, (ImmSubFromXLen uimmlog2xlen:$shamt))>;
499} // Predicates = [HasStdExtZbbOrZbkb]
500
501let Predicates = [HasStdExtZbbOrZbkb, IsRV64] in {
502def : PatGprGpr<shiftopw<riscv_rolw>, ROLW>;
503def : PatGprGpr<shiftopw<riscv_rorw>, RORW>;
504def : PatGprImm<riscv_rorw, RORIW, uimm5>;
505def : Pat<(riscv_rolw GPR:$rs1, uimm5:$rs2),
506          (RORIW GPR:$rs1, (ImmSubFrom32 uimm5:$rs2))>;
507} // Predicates = [HasStdExtZbbOrZbkb, IsRV64]
508
509let Predicates = [HasStdExtZbs] in {
510def : Pat<(XLenVT (and (not (shiftop<shl> 1, (XLenVT GPR:$rs2))), GPR:$rs1)),
511          (BCLR GPR:$rs1, GPR:$rs2)>;
512def : Pat<(XLenVT (and (rotl -2, (XLenVT GPR:$rs2)), GPR:$rs1)),
513          (BCLR GPR:$rs1, GPR:$rs2)>;
514def : Pat<(XLenVT (or (shiftop<shl> 1, (XLenVT GPR:$rs2)), GPR:$rs1)),
515          (BSET GPR:$rs1, GPR:$rs2)>;
516def : Pat<(XLenVT (xor (shiftop<shl> 1, (XLenVT GPR:$rs2)), GPR:$rs1)),
517          (BINV GPR:$rs1, GPR:$rs2)>;
518def : Pat<(XLenVT (and (shiftop<srl> GPR:$rs1, (XLenVT GPR:$rs2)), 1)),
519          (BEXT GPR:$rs1, GPR:$rs2)>;
520
521def : Pat<(XLenVT (shiftop<shl> 1, (XLenVT GPR:$rs2))),
522          (BSET (XLenVT X0), GPR:$rs2)>;
523def : Pat<(XLenVT (not (shiftop<shl> -1, (XLenVT GPR:$rs2)))),
524          (ADDI (XLenVT (BSET (XLenVT X0), GPR:$rs2)), -1)>;
525
526def : Pat<(XLenVT (and GPR:$rs1, BCLRMask:$mask)),
527          (BCLRI GPR:$rs1, BCLRMask:$mask)>;
528def : Pat<(XLenVT (or GPR:$rs1, SingleBitSetMask:$mask)),
529          (BSETI GPR:$rs1, SingleBitSetMask:$mask)>;
530def : Pat<(XLenVT (xor GPR:$rs1, SingleBitSetMask:$mask)),
531          (BINVI GPR:$rs1, SingleBitSetMask:$mask)>;
532
533def : Pat<(XLenVT (and (srl GPR:$rs1, uimmlog2xlen:$shamt), (XLenVT 1))),
534          (BEXTI GPR:$rs1, uimmlog2xlen:$shamt)>;
535
536def : Pat<(XLenVT (seteq (XLenVT (and GPR:$rs1, SingleBitSetMask:$mask)), 0)),
537          (BEXTI (XLenVT (XORI GPR:$rs1, -1)), SingleBitSetMask:$mask)>;
538
539def : Pat<(XLenVT (or GPR:$r, BSETINVTwoBitsMask:$i)),
540          (BSETI (XLenVT (BSETI GPR:$r, (TrailingZeros BSETINVTwoBitsMask:$i))),
541                 (BSETINVTwoBitsMaskHigh BSETINVTwoBitsMask:$i))>;
542def : Pat<(XLenVT (xor GPR:$r, BSETINVTwoBitsMask:$i)),
543          (BINVI (XLenVT (BINVI GPR:$r, (TrailingZeros BSETINVTwoBitsMask:$i))),
544                 (BSETINVTwoBitsMaskHigh BSETINVTwoBitsMask:$i))>;
545def : Pat<(XLenVT (or GPR:$r, BSETINVORIMask:$i)),
546          (BSETI (XLenVT (ORI GPR:$r, (BSETINVORIMaskLow BSETINVORIMask:$i))),
547                 (BSETINVTwoBitsMaskHigh BSETINVORIMask:$i))>;
548def : Pat<(XLenVT (xor GPR:$r, BSETINVORIMask:$i)),
549          (BINVI (XLenVT (XORI GPR:$r, (BSETINVORIMaskLow BSETINVORIMask:$i))),
550                 (BSETINVTwoBitsMaskHigh BSETINVORIMask:$i))>;
551def : Pat<(XLenVT (and GPR:$r, BCLRITwoBitsMask:$i)),
552          (BCLRI (XLenVT (BCLRI GPR:$r, (BCLRITwoBitsMaskLow BCLRITwoBitsMask:$i))),
553                 (BCLRITwoBitsMaskHigh BCLRITwoBitsMask:$i))>;
554def : Pat<(XLenVT (and GPR:$r, BCLRIANDIMask:$i)),
555          (BCLRI (XLenVT (ANDI GPR:$r, (BCLRIANDIMaskLow BCLRIANDIMask:$i))),
556                 (BCLRITwoBitsMaskHigh BCLRIANDIMask:$i))>;
557} // Predicates = [HasStdExtZbs]
558
559let Predicates = [HasStdExtZbb] in
560def : PatGpr<riscv_orc_b, ORC_B>;
561
562let Predicates = [HasStdExtZbkb] in
563def : PatGpr<riscv_brev8, BREV8>;
564
565let Predicates = [HasStdExtZbkb, IsRV32] in {
566// We treat zip and unzip as separate instructions, so match it directly.
567def : PatGpr<riscv_zip, ZIP_RV32, i32>;
568def : PatGpr<riscv_unzip, UNZIP_RV32, i32>;
569} // Predicates = [HasStdExtZbkb, IsRV32]
570
571let Predicates = [HasStdExtZbb] in {
572def : PatGpr<ctlz, CLZ>;
573def : PatGpr<cttz, CTZ>;
574def : PatGpr<ctpop, CPOP>;
575} // Predicates = [HasStdExtZbb]
576
577let Predicates = [HasStdExtZbb, IsRV64] in {
578def : PatGpr<riscv_clzw, CLZW>;
579def : PatGpr<riscv_ctzw, CTZW>;
580def : Pat<(i64 (ctpop (i64 (zexti32 (i64 GPR:$rs1))))), (CPOPW GPR:$rs1)>;
581
582def : Pat<(i64 (riscv_absw GPR:$rs1)),
583          (MAX GPR:$rs1, (XLenVT (SUBW (XLenVT X0), GPR:$rs1)))>;
584} // Predicates = [HasStdExtZbb, IsRV64]
585
586let Predicates = [HasStdExtZbb] in {
587def : Pat<(XLenVT (sext_inreg GPR:$rs1, i8)), (SEXT_B GPR:$rs1)>;
588def : Pat<(XLenVT (sext_inreg GPR:$rs1, i16)), (SEXT_H GPR:$rs1)>;
589} // Predicates = [HasStdExtZbb]
590
591let Predicates = [HasStdExtZbb] in {
592def : PatGprGpr<smin, MIN>;
593def : PatGprGpr<smax, MAX>;
594def : PatGprGpr<umin, MINU>;
595def : PatGprGpr<umax, MAXU>;
596} // Predicates = [HasStdExtZbb]
597
598let Predicates = [HasStdExtZbbOrZbkb, IsRV32] in
599def : PatGpr<bswap, REV8_RV32, i32>;
600
601let Predicates = [HasStdExtZbbOrZbkb, IsRV64] in
602def : PatGpr<bswap, REV8_RV64, i64>;
603
604let Predicates = [HasStdExtZbkb] in {
605def : Pat<(or (and (shl GPR:$rs2, (XLenVT 8)), 0xFFFF),
606              (zexti8 (XLenVT GPR:$rs1))),
607          (PACKH GPR:$rs1, GPR:$rs2)>;
608def : Pat<(or (shl (zexti8 (XLenVT GPR:$rs2)), (XLenVT 8)),
609              (zexti8 (XLenVT GPR:$rs1))),
610          (PACKH GPR:$rs1, GPR:$rs2)>;
611def : Pat<(and (or (shl GPR:$rs2, (XLenVT 8)),
612                   (zexti8 (XLenVT GPR:$rs1))), 0xFFFF),
613          (PACKH GPR:$rs1, GPR:$rs2)>;
614def : Pat<(or (shl (zexti8 (XLenVT GPR:$rs2)), (XLenVT 24)),
615              (shl (zexti8 (XLenVT GPR:$rs1)), (XLenVT 16))),
616          (SLLI (XLenVT (PACKH GPR:$rs1, GPR:$rs2)), (XLenVT 16))>;
617
618def : Pat<(binop_allhusers<or> (shl GPR:$rs2, (XLenVT 8)),
619                               (zexti8 (XLenVT GPR:$rs1))),
620          (PACKH GPR:$rs1, GPR:$rs2)>;
621} // Predicates = [HasStdExtZbkb]
622
623let Predicates = [HasStdExtZbkb, IsRV32] in {
624def : Pat<(i32 (or (zexti16 (i32 GPR:$rs1)), (shl GPR:$rs2, (i32 16)))),
625          (PACK GPR:$rs1, GPR:$rs2)>;
626def : Pat<(or (or
627                  (shl (zexti8 (XLenVT GPR:$op1rs2)), (XLenVT 24)),
628                  (shl (zexti8 (XLenVT GPR:$op1rs1)), (XLenVT 16))),
629              (or
630                  (shl (zexti8 (XLenVT GPR:$op0rs2)), (XLenVT 8)),
631                  (zexti8 (XLenVT GPR:$op0rs1)))),
632          (PACK (XLenVT (PACKH GPR:$op0rs1, GPR:$op0rs2)),
633                (XLenVT (PACKH GPR:$op1rs1, GPR:$op1rs2)))>;
634}
635
636let Predicates = [HasStdExtZbkb, IsRV64] in {
637def : Pat<(i64 (or (zexti32 (i64 GPR:$rs1)), (shl GPR:$rs2, (i64 32)))),
638          (PACK GPR:$rs1, GPR:$rs2)>;
639
640def : Pat<(binop_allwusers<or> (shl GPR:$rs2, (i64 16)),
641                               (zexti16 (i64 GPR:$rs1))),
642          (PACKW GPR:$rs1, GPR:$rs2)>;
643def : Pat<(i64 (or (sext_inreg (shl GPR:$rs2, (i64 16)), i32),
644                   (zexti16 (i64 GPR:$rs1)))),
645          (PACKW GPR:$rs1, GPR:$rs2)>;
646} // Predicates = [HasStdExtZbkb, IsRV64]
647
648let Predicates = [HasStdExtZbb, IsRV32] in
649def : Pat<(i32 (and GPR:$rs, 0xFFFF)), (ZEXT_H_RV32 GPR:$rs)>;
650let Predicates = [HasStdExtZbb, IsRV64] in
651def : Pat<(i64 (and GPR:$rs, 0xFFFF)), (ZEXT_H_RV64 GPR:$rs)>;
652
653let Predicates = [HasStdExtZbkb, NoStdExtZbb, IsRV32] in
654def : Pat<(i32 (and GPR:$rs, 0xFFFF)), (PACK GPR:$rs, (XLenVT X0))>;
655let Predicates = [HasStdExtZbkb, NoStdExtZbb, IsRV64] in
656def : Pat<(i64 (and GPR:$rs, 0xFFFF)), (PACKW GPR:$rs, (XLenVT X0))>;
657
658let Predicates = [HasStdExtZba] in {
659
660foreach i = {1,2,3} in {
661  defvar shxadd = !cast<Instruction>("SH"#i#"ADD");
662  def : Pat<(XLenVT (add_like_non_imm12 (shl GPR:$rs1, (XLenVT i)), GPR:$rs2)),
663            (shxadd GPR:$rs1, GPR:$rs2)>;
664  def : Pat<(XLenVT (riscv_shl_add GPR:$rs1, (XLenVT i), GPR:$rs2)),
665            (shxadd GPR:$rs1, GPR:$rs2)>;
666
667  defvar pat = !cast<ComplexPattern>("sh"#i#"add_op");
668  // More complex cases use a ComplexPattern.
669  def : Pat<(XLenVT (add_like_non_imm12 pat:$rs1, GPR:$rs2)),
670            (shxadd pat:$rs1, GPR:$rs2)>;
671}
672
673def : Pat<(add_like (XLenVT GPR:$r), CSImm12MulBy4:$i),
674          (SH2ADD (XLenVT (ADDI (XLenVT X0), CSImm12MulBy4:$i)),
675                  GPR:$r)>;
676def : Pat<(add_like (XLenVT GPR:$r), CSImm12MulBy8:$i),
677          (SH3ADD (XLenVT (ADDI (XLenVT X0), CSImm12MulBy8:$i)),
678                  GPR:$r)>;
679
680} // Predicates = [HasStdExtZba]
681
682let Predicates = [HasStdExtZba, IsRV64] in {
683def : Pat<(i64 (shl (and GPR:$rs1, 0xFFFFFFFF), uimm5:$shamt)),
684          (SLLI_UW GPR:$rs1, uimm5:$shamt)>;
685// Match a shifted 0xffffffff mask. Use SRLI to clear the LSBs and SLLI_UW to
686// mask and shift.
687def : Pat<(i64 (and GPR:$rs1, Shifted32OnesMask:$mask)),
688          (SLLI_UW (XLenVT (SRLI GPR:$rs1, Shifted32OnesMask:$mask)),
689                   Shifted32OnesMask:$mask)>;
690def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0xFFFFFFFF), GPR:$rs2)),
691          (ADD_UW GPR:$rs1, GPR:$rs2)>;
692def : Pat<(i64 (and GPR:$rs, 0xFFFFFFFF)), (ADD_UW GPR:$rs, (XLenVT X0))>;
693
694foreach i = {1,2,3} in {
695  defvar shxadd_uw = !cast<Instruction>("SH"#i#"ADD_UW");
696  def : Pat<(i64 (add_like_non_imm12 (shl (and GPR:$rs1, 0xFFFFFFFF), (i64 i)), (XLenVT GPR:$rs2))),
697            (shxadd_uw GPR:$rs1, GPR:$rs2)>;
698  def : Pat<(i64 (riscv_shl_add (and GPR:$rs1, 0xFFFFFFFF), (i64 i), GPR:$rs2)),
699            (shxadd_uw GPR:$rs1, GPR:$rs2)>;
700}
701
702def : Pat<(i64 (add_like_non_imm12 (and (shl GPR:$rs1, (i64 1)), 0x1FFFFFFFF), (XLenVT GPR:$rs2))),
703          (SH1ADD_UW GPR:$rs1, GPR:$rs2)>;
704def : Pat<(i64 (add_like_non_imm12 (and (shl GPR:$rs1, (i64 2)), 0x3FFFFFFFF), (XLenVT GPR:$rs2))),
705          (SH2ADD_UW GPR:$rs1, GPR:$rs2)>;
706def : Pat<(i64 (add_like_non_imm12 (and (shl GPR:$rs1, (i64 3)), 0x7FFFFFFFF), (XLenVT GPR:$rs2))),
707          (SH3ADD_UW GPR:$rs1, GPR:$rs2)>;
708
709// More complex cases use a ComplexPattern.
710foreach i = {1,2,3} in {
711  defvar pat = !cast<ComplexPattern>("sh"#i#"add_uw_op");
712  def : Pat<(i64 (add_like_non_imm12 pat:$rs1, (XLenVT GPR:$rs2))),
713            (!cast<Instruction>("SH"#i#"ADD_UW") pat:$rs1, GPR:$rs2)>;
714}
715
716def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0xFFFFFFFE), (XLenVT GPR:$rs2))),
717          (SH1ADD (XLenVT (SRLIW GPR:$rs1, 1)), GPR:$rs2)>;
718def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0xFFFFFFFC), (XLenVT GPR:$rs2))),
719          (SH2ADD (XLenVT (SRLIW GPR:$rs1, 2)), GPR:$rs2)>;
720def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0xFFFFFFF8), (XLenVT GPR:$rs2))),
721          (SH3ADD (XLenVT (SRLIW GPR:$rs1, 3)), GPR:$rs2)>;
722
723// Use SRLI to clear the LSBs and SHXADD_UW to mask and shift.
724def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0x1FFFFFFFE), (XLenVT GPR:$rs2))),
725          (SH1ADD_UW (XLenVT (SRLI GPR:$rs1, 1)), GPR:$rs2)>;
726def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0x3FFFFFFFC), (XLenVT GPR:$rs2))),
727          (SH2ADD_UW (XLenVT (SRLI GPR:$rs1, 2)), GPR:$rs2)>;
728def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0x7FFFFFFF8), (XLenVT GPR:$rs2))),
729          (SH3ADD_UW (XLenVT (SRLI GPR:$rs1, 3)), GPR:$rs2)>;
730
731} // Predicates = [HasStdExtZba, IsRV64]
732
733let Predicates = [HasStdExtZbcOrZbkc] in {
734def : PatGprGpr<riscv_clmul, CLMUL>;
735def : PatGprGpr<riscv_clmulh, CLMULH>;
736} // Predicates = [HasStdExtZbcOrZbkc]
737
738let Predicates = [HasStdExtZbc] in
739def : PatGprGpr<riscv_clmulr, CLMULR>;
740
741let Predicates = [HasStdExtZbkx] in {
742def : PatGprGpr<int_riscv_xperm4, XPERM4>;
743def : PatGprGpr<int_riscv_xperm8, XPERM8>;
744} // Predicates = [HasStdExtZbkx]
745