1 //===-- RISCVInstrInfoZb.td - RISC-V Bitmanip instructions -*- tablegen -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file describes the RISC-V instructions from the standard Bitmanip
10 // extensions, versions:
16 // This file also describes RISC-V instructions from the Zbk* extensions in
17 // Cryptography Extensions Volume I: Scalar & Entropy Source Instructions,
23 //===----------------------------------------------------------------------===//
25 //===----------------------------------------------------------------------===//
26 // Operand and SDNode transformation definitions.
27 //===----------------------------------------------------------------------===//
29 def SDTIntShiftAddOp : SDTypeProfile<1, 3, [ // shl_add
30 SDTCisSameAs<0, 1>, SDTCisSameAs<0, 3>, SDTCisInt<0>, SDTCisInt<2>,
34 def riscv_shl_add : SDNode<"RISCVISD::SHL_ADD", SDTIntShiftAddOp>;
35 def riscv_clzw : SDNode<"RISCVISD::CLZW", SDT_RISCVIntUnaryOpW>;
36 def riscv_ctzw : SDNode<"RISCVISD::CTZW", SDT_RISCVIntUnaryOpW>;
37 def riscv_rolw : SDNode<"RISCVISD::ROLW", SDT_RISCVIntBinOpW>;
38 def riscv_rorw : SDNode<"RISCVISD::RORW", SDT_RISCVIntBinOpW>;
39 def riscv_brev8 : SDNode<"RISCVISD::BREV8", SDTIntUnaryOp>;
40 def riscv_orc_b : SDNode<"RISCVISD::ORC_B", SDTIntUnaryOp>;
41 def riscv_zip : SDNode<"RISCVISD::ZIP", SDTIntUnaryOp>;
42 def riscv_unzip : SDNode<"RISCVISD::UNZIP", SDTIntUnaryOp>;
43 def riscv_absw : SDNode<"RISCVISD::ABSW", SDTIntUnaryOp>;
44 def riscv_clmul : SDNode<"RISCVISD::CLMUL", SDTIntBinOp>;
45 def riscv_clmulh : SDNode<"RISCVISD::CLMULH", SDTIntBinOp>;
46 def riscv_clmulr : SDNode<"RISCVISD::CLMULR", SDTIntBinOp>;
48 def BCLRXForm : SDNodeXForm<imm, [{
50 return CurDAG->getTargetConstant(llvm::countr_one(N->getZExtValue()),
51 SDLoc(N), N->getValueType(0));
54 def SingleBitSetMaskToIndex : SDNodeXForm<imm, [{
56 return CurDAG->getTargetConstant(llvm::countr_zero(N->getZExtValue()),
57 SDLoc(N), N->getValueType(0));
60 // Checks if this mask has a single 0 bit and cannot be used with ANDI.
61 def BCLRMask : ImmLeaf<XLenVT, [{
62 if (Subtarget->is64Bit())
63 return !isInt<12>(Imm) && isPowerOf2_64(~Imm);
64 return !isInt<12>(Imm) && isPowerOf2_32(~Imm);
67 // Checks if this mask has a single 1 bit and cannot be used with ORI/XORI.
68 def 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>;
74 // Check if (or r, i) can be optimized to (BSETI (BSETI r, i0), i1),
75 // in which i = (1 << i0) | (1 << i1).
76 def BSETINVTwoBitsMask : PatLeaf<(imm), [{
79 // The immediate should not be a simm12.
80 if (isInt<12>(N->getSExtValue()))
82 // The immediate must have exactly two bits set.
83 return llvm::popcount(N->getZExtValue()) == 2;
86 def BSETINVTwoBitsMaskHigh : SDNodeXForm<imm, [{
87 uint64_t I = N->getZExtValue();
88 return CurDAG->getTargetConstant(llvm::Log2_64(I), SDLoc(N),
92 // Check if (or r, imm) can be optimized to (BSETI (ORI r, i0), i1),
93 // in which imm = i0 | (1 << i1).
94 def BSETINVORIMask : PatLeaf<(imm), [{
97 // The immediate should not be a simm12.
98 if (isInt<12>(N->getSExtValue()))
100 // There should be only one set bit from bit 11 to the top.
101 return isPowerOf2_64(N->getZExtValue() & ~0x7ff);
104 def BSETINVORIMaskLow : SDNodeXForm<imm, [{
105 return CurDAG->getTargetConstant(N->getZExtValue() & 0x7ff,
106 SDLoc(N), N->getValueType(0));
109 // Check if (and r, i) can be optimized to (BCLRI (BCLRI r, i0), i1),
110 // in which i = ~((1<<i0) | (1<<i1)).
111 def BCLRITwoBitsMask : PatLeaf<(imm), [{
114 // The immediate should not be a simm12.
115 if (isInt<12>(N->getSExtValue()))
117 // The immediate must have exactly two bits clear.
118 return (unsigned)llvm::popcount(N->getZExtValue()) == Subtarget->getXLen() - 2;
121 def BCLRITwoBitsMaskLow : SDNodeXForm<imm, [{
122 return CurDAG->getTargetConstant(llvm::countr_zero(~N->getZExtValue()),
123 SDLoc(N), N->getValueType(0));
126 def 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),
134 // Check if (and r, i) can be optimized to (BCLRI (ANDI r, i0), i1),
135 // in which i = i0 & ~(1<<i1).
136 def BCLRIANDIMask : PatLeaf<(imm), [{
139 // The immediate should not be a simm12.
140 if (isInt<12>(N->getSExtValue()))
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);
147 def BCLRIANDIMaskLow : SDNodeXForm<imm, [{
148 return CurDAG->getSignedTargetConstant((N->getZExtValue() & 0x7ff) | ~0x7ffull,
149 SDLoc(N), N->getValueType(0));
152 def SimmShiftRightBy2XForm : SDNodeXForm<imm, [{
153 return CurDAG->getSignedTargetConstant(N->getSExtValue() >> 2, SDLoc(N),
157 def SimmShiftRightBy3XForm : SDNodeXForm<imm, [{
158 return CurDAG->getSignedTargetConstant(N->getSExtValue() >> 3, SDLoc(N),
162 def CSImm12MulBy4 : PatLeaf<(imm), [{
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>;
170 def CSImm12MulBy8 : PatLeaf<(imm), [{
173 int64_t C = N->getSExtValue();
174 // Skip if C is simm12, an lui or can be optimized by the PatLeaf AddiPair or
176 return !isInt<14>(C) && !isShiftedInt<20, 12>(C) && isShiftedInt<12, 3>(C);
177 }], SimmShiftRightBy3XForm>;
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`.
183 class 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());
188 let PredicateCodeUsesOperands = 1;
189 let GISelPredicateCode = [{
190 const MachineOperand &ImmOp = *Operands[1];
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());
201 def add_non_imm12 : binop_with_non_imm12<add>;
202 def add_like_non_imm12 : binop_with_non_imm12<add_like>;
204 def Shifted32OnesMask : IntImmLeaf<XLenVT, [{
205 if (!Imm.isShiftedMask())
208 unsigned TrailingZeros = Imm.countr_zero();
209 return TrailingZeros > 0 && TrailingZeros < 32 &&
210 Imm == UINT64_C(0xFFFFFFFF) << TrailingZeros;
213 def sh1add_op : ComplexPattern<XLenVT, 1, "selectSHXADDOp<1>", [], [], 6>;
214 def sh2add_op : ComplexPattern<XLenVT, 1, "selectSHXADDOp<2>", [], [], 6>;
215 def sh3add_op : ComplexPattern<XLenVT, 1, "selectSHXADDOp<3>", [], [], 6>;
216 def gi_sh1add_op : GIComplexOperandMatcher<s32, "selectSHXADDOp<1>">,
217 GIComplexPatternEquiv<sh1add_op>;
218 def gi_sh2add_op : GIComplexOperandMatcher<s32, "selectSHXADDOp<2>">,
219 GIComplexPatternEquiv<sh2add_op>;
220 def gi_sh3add_op : GIComplexOperandMatcher<s32, "selectSHXADDOp<3>">,
221 GIComplexPatternEquiv<sh3add_op>;
224 def sh1add_uw_op : ComplexPattern<XLenVT, 1, "selectSHXADD_UWOp<1>", [], [], 6>;
225 def sh2add_uw_op : ComplexPattern<XLenVT, 1, "selectSHXADD_UWOp<2>", [], [], 6>;
226 def sh3add_uw_op : ComplexPattern<XLenVT, 1, "selectSHXADD_UWOp<3>", [], [], 6>;
227 def gi_sh1add_uw_op : GIComplexOperandMatcher<s32, "selectSHXADD_UWOp<1>">,
228 GIComplexPatternEquiv<sh1add_uw_op>;
229 def gi_sh2add_uw_op : GIComplexOperandMatcher<s32, "selectSHXADD_UWOp<2>">,
230 GIComplexPatternEquiv<sh2add_uw_op>;
231 def gi_sh3add_uw_op : GIComplexOperandMatcher<s32, "selectSHXADD_UWOp<3>">,
232 GIComplexPatternEquiv<sh3add_uw_op>;
234 //===----------------------------------------------------------------------===//
235 // Instruction class templates
236 //===----------------------------------------------------------------------===//
238 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
239 class 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"> {
246 let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
247 class RVBShift_ri<bits<5> imm11_7, bits<3> funct3, RISCVOpcode opcode,
249 : RVInstIShift<imm11_7, funct3, opcode, (outs GPR:$rd),
250 (ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr,
251 "$rd, $rs1, $shamt">;
253 //===----------------------------------------------------------------------===//
255 //===----------------------------------------------------------------------===//
257 let Predicates = [HasStdExtZbbOrZbkb] in {
258 def ANDN : ALU_rr<0b0100000, 0b111, "andn">,
259 Sched<[WriteIALU, ReadIALU, ReadIALU]>;
260 def ORN : ALU_rr<0b0100000, 0b110, "orn">,
261 Sched<[WriteIALU, ReadIALU, ReadIALU]>;
262 def XNOR : ALU_rr<0b0100000, 0b100, "xnor">,
263 Sched<[WriteIALU, ReadIALU, ReadIALU]>;
264 } // Predicates = [HasStdExtZbbOrZbkb]
266 let Predicates = [HasStdExtZba] in {
267 def SH1ADD : ALU_rr<0b0010000, 0b010, "sh1add">,
268 Sched<[WriteSHXADD, ReadSHXADD, ReadSHXADD]>;
269 def SH2ADD : ALU_rr<0b0010000, 0b100, "sh2add">,
270 Sched<[WriteSHXADD, ReadSHXADD, ReadSHXADD]>;
271 def SH3ADD : ALU_rr<0b0010000, 0b110, "sh3add">,
272 Sched<[WriteSHXADD, ReadSHXADD, ReadSHXADD]>;
273 } // Predicates = [HasStdExtZba]
275 let Predicates = [HasStdExtZba, IsRV64] in {
276 def SLLI_UW : RVBShift_ri<0b00001, 0b001, OPC_OP_IMM_32, "slli.uw">,
277 Sched<[WriteShiftImm32, ReadShiftImm32]>;
278 def ADD_UW : ALUW_rr<0b0000100, 0b000, "add.uw">,
279 Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;
280 def SH1ADD_UW : ALUW_rr<0b0010000, 0b010, "sh1add.uw">,
281 Sched<[WriteSHXADD32, ReadSHXADD32, ReadSHXADD32]>;
282 def SH2ADD_UW : ALUW_rr<0b0010000, 0b100, "sh2add.uw">,
283 Sched<[WriteSHXADD32, ReadSHXADD32, ReadSHXADD32]>;
284 def SH3ADD_UW : ALUW_rr<0b0010000, 0b110, "sh3add.uw">,
285 Sched<[WriteSHXADD32, ReadSHXADD32, ReadSHXADD32]>;
286 } // Predicates = [HasStdExtZba, IsRV64]
288 let Predicates = [HasStdExtZbbOrZbkb] in {
289 def ROL : ALU_rr<0b0110000, 0b001, "rol">,
290 Sched<[WriteRotateReg, ReadRotateReg, ReadRotateReg]>;
291 def ROR : ALU_rr<0b0110000, 0b101, "ror">,
292 Sched<[WriteRotateReg, ReadRotateReg, ReadRotateReg]>;
294 def RORI : Shift_ri<0b01100, 0b101, "rori">,
295 Sched<[WriteRotateImm, ReadRotateImm]>;
296 } // Predicates = [HasStdExtZbbOrZbkb]
298 let Predicates = [HasStdExtZbbOrZbkb, IsRV64], IsSignExtendingOpW = 1 in {
299 def ROLW : ALUW_rr<0b0110000, 0b001, "rolw">,
300 Sched<[WriteRotateReg32, ReadRotateReg32, ReadRotateReg32]>;
301 def RORW : ALUW_rr<0b0110000, 0b101, "rorw">,
302 Sched<[WriteRotateReg32, ReadRotateReg32, ReadRotateReg32]>;
304 def RORIW : ShiftW_ri<0b0110000, 0b101, "roriw">,
305 Sched<[WriteRotateImm32, ReadRotateImm32]>;
306 } // Predicates = [HasStdExtZbbOrZbkb, IsRV64]
308 let Predicates = [HasStdExtZbs] in {
309 def BCLR : ALU_rr<0b0100100, 0b001, "bclr">,
310 Sched<[WriteSingleBit, ReadSingleBit, ReadSingleBit]>;
311 def BSET : ALU_rr<0b0010100, 0b001, "bset">,
312 Sched<[WriteSingleBit, ReadSingleBit, ReadSingleBit]>;
313 def BINV : ALU_rr<0b0110100, 0b001, "binv">,
314 Sched<[WriteSingleBit, ReadSingleBit, ReadSingleBit]>;
315 let IsSignExtendingOpW = 1 in
316 def BEXT : ALU_rr<0b0100100, 0b101, "bext">,
317 Sched<[WriteBEXT, ReadSingleBit, ReadSingleBit]>;
319 def BCLRI : Shift_ri<0b01001, 0b001, "bclri">,
320 Sched<[WriteSingleBitImm, ReadSingleBitImm]>;
321 def BSETI : Shift_ri<0b00101, 0b001, "bseti">,
322 Sched<[WriteSingleBitImm, ReadSingleBitImm]>;
323 def BINVI : Shift_ri<0b01101, 0b001, "binvi">,
324 Sched<[WriteSingleBitImm, ReadSingleBitImm]>;
325 let IsSignExtendingOpW = 1 in
326 def BEXTI : Shift_ri<0b01001, 0b101, "bexti">,
327 Sched<[WriteBEXTI, ReadSingleBitImm]>;
328 } // Predicates = [HasStdExtZbs]
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.
333 let Predicates = [HasStdExtZbkx] in {
334 def XPERM4 : ALU_rr<0b0010100, 0b010, "xperm4">,
335 Sched<[WriteXPERM, ReadXPERM, ReadXPERM]>;
336 def XPERM8 : ALU_rr<0b0010100, 0b100, "xperm8">,
337 Sched<[WriteXPERM, ReadXPERM, ReadXPERM]>;
338 } // Predicates = [HasStdExtZbkx]
340 let Predicates = [HasStdExtZbb], IsSignExtendingOpW = 1 in {
341 def CLZ : Unary_r<0b011000000000, 0b001, "clz">,
342 Sched<[WriteCLZ, ReadCLZ]>;
343 def CTZ : Unary_r<0b011000000001, 0b001, "ctz">,
344 Sched<[WriteCTZ, ReadCTZ]>;
345 def CPOP : Unary_r<0b011000000010, 0b001, "cpop">,
346 Sched<[WriteCPOP, ReadCPOP]>;
347 } // Predicates = [HasStdExtZbb]
349 let Predicates = [HasStdExtZbb, IsRV64], IsSignExtendingOpW = 1 in {
350 def CLZW : UnaryW_r<0b011000000000, 0b001, "clzw">,
351 Sched<[WriteCLZ32, ReadCLZ32]>;
352 def CTZW : UnaryW_r<0b011000000001, 0b001, "ctzw">,
353 Sched<[WriteCTZ32, ReadCTZ32]>;
354 def CPOPW : UnaryW_r<0b011000000010, 0b001, "cpopw">,
355 Sched<[WriteCPOP32, ReadCPOP32]>;
356 } // Predicates = [HasStdExtZbb, IsRV64]
358 let Predicates = [HasStdExtZbb], IsSignExtendingOpW = 1 in {
359 def SEXT_B : Unary_r<0b011000000100, 0b001, "sext.b">,
360 Sched<[WriteIALU, ReadIALU]>;
361 def SEXT_H : Unary_r<0b011000000101, 0b001, "sext.h">,
362 Sched<[WriteIALU, ReadIALU]>;
363 } // Predicates = [HasStdExtZbb]
365 let Predicates = [HasStdExtZbc] in {
366 def CLMULR : ALU_rr<0b0000101, 0b010, "clmulr", Commutable=1>,
367 Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>;
368 } // Predicates = [HasStdExtZbc]
370 let Predicates = [HasStdExtZbcOrZbkc] in {
371 def CLMUL : ALU_rr<0b0000101, 0b001, "clmul", Commutable=1>,
372 Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>;
373 def CLMULH : ALU_rr<0b0000101, 0b011, "clmulh", Commutable=1>,
374 Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>;
375 } // Predicates = [HasStdExtZbcOrZbkc]
377 let Predicates = [HasStdExtZbb] in {
378 def MIN : ALU_rr<0b0000101, 0b100, "min", Commutable=1>,
379 Sched<[WriteIMinMax, ReadIMinMax, ReadIMinMax]>;
380 def MINU : ALU_rr<0b0000101, 0b101, "minu", Commutable=1>,
381 Sched<[WriteIMinMax, ReadIMinMax, ReadIMinMax]>;
382 def MAX : ALU_rr<0b0000101, 0b110, "max", Commutable=1>,
383 Sched<[WriteIMinMax, ReadIMinMax, ReadIMinMax]>;
384 def MAXU : ALU_rr<0b0000101, 0b111, "maxu", Commutable=1>,
385 Sched<[WriteIMinMax, ReadIMinMax, ReadIMinMax]>;
386 } // Predicates = [HasStdExtZbb]
388 let Predicates = [HasStdExtZbkb] in {
389 def PACK : ALU_rr<0b0000100, 0b100, "pack">,
390 Sched<[WritePACK, ReadPACK, ReadPACK]>;
391 let IsSignExtendingOpW = 1 in
392 def PACKH : ALU_rr<0b0000100, 0b111, "packh">,
393 Sched<[WritePACK, ReadPACK, ReadPACK]>;
394 } // Predicates = [HasStdExtZbkb]
396 let Predicates = [HasStdExtZbkb, IsRV64], IsSignExtendingOpW = 1 in
397 def PACKW : ALUW_rr<0b0000100, 0b100, "packw">,
398 Sched<[WritePACK32, ReadPACK32, ReadPACK32]>;
400 let Predicates = [HasStdExtZbb, IsRV32] in {
401 def ZEXT_H_RV32 : RVBUnaryR<0b0000100, 0b100, OPC_OP, "zext.h">,
402 Sched<[WriteIALU, ReadIALU]>;
403 } // Predicates = [HasStdExtZbb, IsRV32]
405 let Predicates = [HasStdExtZbb, IsRV64], IsSignExtendingOpW = 1 in {
406 def ZEXT_H_RV64 : RVBUnaryR<0b0000100, 0b100, OPC_OP_32, "zext.h">,
407 Sched<[WriteIALU, ReadIALU]>;
408 } // Predicates = [HasStdExtZbb, IsRV64]
410 let Predicates = [HasStdExtZbbOrZbkb, IsRV32] in {
411 def REV8_RV32 : Unary_r<0b011010011000, 0b101, "rev8">,
412 Sched<[WriteREV8, ReadREV8]>;
413 } // Predicates = [HasStdExtZbbOrZbkb, IsRV32]
415 let Predicates = [HasStdExtZbbOrZbkb, IsRV64] in {
416 def REV8_RV64 : Unary_r<0b011010111000, 0b101, "rev8">,
417 Sched<[WriteREV8, ReadREV8]>;
418 } // Predicates = [HasStdExtZbbOrZbkb, IsRV64]
420 let Predicates = [HasStdExtZbb] in {
421 def ORC_B : Unary_r<0b001010000111, 0b101, "orc.b">,
422 Sched<[WriteORCB, ReadORCB]>;
423 } // Predicates = [HasStdExtZbb]
425 let Predicates = [HasStdExtZbkb] in
426 def BREV8 : Unary_r<0b011010000111, 0b101, "brev8">,
427 Sched<[WriteBREV8, ReadBREV8]>;
429 let Predicates = [HasStdExtZbkb, IsRV32] in {
430 def ZIP_RV32 : Unary_r<0b000010001111, 0b001, "zip">,
431 Sched<[WriteZIP, ReadZIP]>;
432 def UNZIP_RV32 : Unary_r<0b000010001111, 0b101, "unzip">,
433 Sched<[WriteZIP, ReadZIP]>;
434 } // Predicates = [HasStdExtZbkb, IsRV32]
437 //===----------------------------------------------------------------------===//
438 // Pseudo Instructions
439 //===----------------------------------------------------------------------===//
441 let Predicates = [HasStdExtZba, IsRV64] in {
442 def : InstAlias<"zext.w $rd, $rs", (ADD_UW GPR:$rd, GPR:$rs, X0)>;
443 } // Predicates = [HasStdExtZba, IsRV64]
445 let Predicates = [HasStdExtZbb] in {
446 def : InstAlias<"ror $rd, $rs1, $shamt",
447 (RORI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>;
448 } // Predicates = [HasStdExtZbb]
450 let Predicates = [HasStdExtZbb, IsRV64] in {
451 def : InstAlias<"rorw $rd, $rs1, $shamt",
452 (RORIW GPR:$rd, GPR:$rs1, uimm5:$shamt), 0>;
453 } // Predicates = [HasStdExtZbb, IsRV64]
455 let Predicates = [HasStdExtZbs] in {
456 def : InstAlias<"bset $rd, $rs1, $shamt",
457 (BSETI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>;
458 def : InstAlias<"bclr $rd, $rs1, $shamt",
459 (BCLRI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>;
460 def : InstAlias<"binv $rd, $rs1, $shamt",
461 (BINVI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>;
462 def : InstAlias<"bext $rd, $rs1, $shamt",
463 (BEXTI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>;
464 } // Predicates = [HasStdExtZbs]
466 let Predicates = [HasStdExtZbkb, NoStdExtZbb, IsRV32] in {
467 def : InstAlias<"zext.h $rd, $rs", (PACK GPR:$rd, GPR:$rs, X0)>;
468 } // Predicates = [HasStdExtZbkb, NoStdExtZbb, IsRV32]
470 let Predicates = [HasStdExtZbkb, NoStdExtZbb, IsRV64] in {
471 def : InstAlias<"zext.h $rd, $rs", (PACKW GPR:$rd, GPR:$rs, X0)>;
472 } // Predicates = [HasStdExtZbkb, NoStdExtZbb, IsRV64]
474 //===----------------------------------------------------------------------===//
476 //===----------------------------------------------------------------------===//
478 def invLogicImm : ComplexPattern<XLenVT, 1, "selectInvLogicImm", [], [], 0>;
480 let Predicates = [HasStdExtZbbOrZbkb] in {
481 def : Pat<(XLenVT (and GPR:$rs1, (not GPR:$rs2))), (ANDN GPR:$rs1, GPR:$rs2)>;
482 def : Pat<(XLenVT (or GPR:$rs1, (not GPR:$rs2))), (ORN GPR:$rs1, GPR:$rs2)>;
483 def : Pat<(XLenVT (xor GPR:$rs1, (not GPR:$rs2))), (XNOR GPR:$rs1, GPR:$rs2)>;
485 def : Pat<(XLenVT (and GPR:$rs1, invLogicImm:$rs2)), (ANDN GPR:$rs1, invLogicImm:$rs2)>;
486 def : Pat<(XLenVT (or GPR:$rs1, invLogicImm:$rs2)), (ORN GPR:$rs1, invLogicImm:$rs2)>;
487 def : Pat<(XLenVT (xor GPR:$rs1, invLogicImm:$rs2)), (XNOR GPR:$rs1, invLogicImm:$rs2)>;
488 } // Predicates = [HasStdExtZbbOrZbkb]
490 let Predicates = [HasStdExtZbbOrZbkb] in {
491 def : PatGprGpr<shiftop<rotl>, ROL>;
492 def : PatGprGpr<shiftop<rotr>, ROR>;
494 def : 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.
497 def : Pat<(XLenVT (rotl GPR:$rs1, uimmlog2xlen:$shamt)),
498 (RORI GPR:$rs1, (ImmSubFromXLen uimmlog2xlen:$shamt))>;
499 } // Predicates = [HasStdExtZbbOrZbkb]
501 let Predicates = [HasStdExtZbbOrZbkb, IsRV64] in {
502 def : PatGprGpr<shiftopw<riscv_rolw>, ROLW>;
503 def : PatGprGpr<shiftopw<riscv_rorw>, RORW>;
504 def : PatGprImm<riscv_rorw, RORIW, uimm5>;
505 def : Pat<(riscv_rolw GPR:$rs1, uimm5:$rs2),
506 (RORIW GPR:$rs1, (ImmSubFrom32 uimm5:$rs2))>;
507 } // Predicates = [HasStdExtZbbOrZbkb, IsRV64]
509 let Predicates = [HasStdExtZbs] in {
510 def : Pat<(XLenVT (and (not (shiftop<shl> 1, (XLenVT GPR:$rs2))), GPR:$rs1)),
511 (BCLR GPR:$rs1, GPR:$rs2)>;
512 def : Pat<(XLenVT (and (rotl -2, (XLenVT GPR:$rs2)), GPR:$rs1)),
513 (BCLR GPR:$rs1, GPR:$rs2)>;
514 def : Pat<(XLenVT (or (shiftop<shl> 1, (XLenVT GPR:$rs2)), GPR:$rs1)),
515 (BSET GPR:$rs1, GPR:$rs2)>;
516 def : Pat<(XLenVT (xor (shiftop<shl> 1, (XLenVT GPR:$rs2)), GPR:$rs1)),
517 (BINV GPR:$rs1, GPR:$rs2)>;
518 def : Pat<(XLenVT (and (shiftop<srl> GPR:$rs1, (XLenVT GPR:$rs2)), 1)),
519 (BEXT GPR:$rs1, GPR:$rs2)>;
521 def : Pat<(XLenVT (shiftop<shl> 1, (XLenVT GPR:$rs2))),
522 (BSET (XLenVT X0), GPR:$rs2)>;
523 def : Pat<(XLenVT (not (shiftop<shl> -1, (XLenVT GPR:$rs2)))),
524 (ADDI (XLenVT (BSET (XLenVT X0), GPR:$rs2)), -1)>;
526 def : Pat<(XLenVT (and GPR:$rs1, BCLRMask:$mask)),
527 (BCLRI GPR:$rs1, BCLRMask:$mask)>;
528 def : Pat<(XLenVT (or GPR:$rs1, SingleBitSetMask:$mask)),
529 (BSETI GPR:$rs1, SingleBitSetMask:$mask)>;
530 def : Pat<(XLenVT (xor GPR:$rs1, SingleBitSetMask:$mask)),
531 (BINVI GPR:$rs1, SingleBitSetMask:$mask)>;
533 def : Pat<(XLenVT (and (srl GPR:$rs1, uimmlog2xlen:$shamt), (XLenVT 1))),
534 (BEXTI GPR:$rs1, uimmlog2xlen:$shamt)>;
536 def : Pat<(XLenVT (seteq (XLenVT (and GPR:$rs1, SingleBitSetMask:$mask)), 0)),
537 (BEXTI (XLenVT (XORI GPR:$rs1, -1)), SingleBitSetMask:$mask)>;
539 def : Pat<(XLenVT (or GPR:$r, BSETINVTwoBitsMask:$i)),
540 (BSETI (XLenVT (BSETI GPR:$r, (TrailingZeros BSETINVTwoBitsMask:$i))),
541 (BSETINVTwoBitsMaskHigh BSETINVTwoBitsMask:$i))>;
542 def : Pat<(XLenVT (xor GPR:$r, BSETINVTwoBitsMask:$i)),
543 (BINVI (XLenVT (BINVI GPR:$r, (TrailingZeros BSETINVTwoBitsMask:$i))),
544 (BSETINVTwoBitsMaskHigh BSETINVTwoBitsMask:$i))>;
545 def : Pat<(XLenVT (or GPR:$r, BSETINVORIMask:$i)),
546 (BSETI (XLenVT (ORI GPR:$r, (BSETINVORIMaskLow BSETINVORIMask:$i))),
547 (BSETINVTwoBitsMaskHigh BSETINVORIMask:$i))>;
548 def : Pat<(XLenVT (xor GPR:$r, BSETINVORIMask:$i)),
549 (BINVI (XLenVT (XORI GPR:$r, (BSETINVORIMaskLow BSETINVORIMask:$i))),
550 (BSETINVTwoBitsMaskHigh BSETINVORIMask:$i))>;
551 def : Pat<(XLenVT (and GPR:$r, BCLRITwoBitsMask:$i)),
552 (BCLRI (XLenVT (BCLRI GPR:$r, (BCLRITwoBitsMaskLow BCLRITwoBitsMask:$i))),
553 (BCLRITwoBitsMaskHigh BCLRITwoBitsMask:$i))>;
554 def : Pat<(XLenVT (and GPR:$r, BCLRIANDIMask:$i)),
555 (BCLRI (XLenVT (ANDI GPR:$r, (BCLRIANDIMaskLow BCLRIANDIMask:$i))),
556 (BCLRITwoBitsMaskHigh BCLRIANDIMask:$i))>;
557 } // Predicates = [HasStdExtZbs]
559 let Predicates = [HasStdExtZbb] in
560 def : PatGpr<riscv_orc_b, ORC_B>;
562 let Predicates = [HasStdExtZbkb] in
563 def : PatGpr<riscv_brev8, BREV8>;
565 let Predicates = [HasStdExtZbkb, IsRV32] in {
566 // We treat zip and unzip as separate instructions, so match it directly.
567 def : PatGpr<riscv_zip, ZIP_RV32, i32>;
568 def : PatGpr<riscv_unzip, UNZIP_RV32, i32>;
569 } // Predicates = [HasStdExtZbkb, IsRV32]
571 let Predicates = [HasStdExtZbb] in {
572 def : PatGpr<ctlz, CLZ>;
573 def : PatGpr<cttz, CTZ>;
574 def : PatGpr<ctpop, CPOP>;
575 } // Predicates = [HasStdExtZbb]
577 let Predicates = [HasStdExtZbb, IsRV64] in {
578 def : PatGpr<riscv_clzw, CLZW>;
579 def : PatGpr<riscv_ctzw, CTZW>;
580 def : Pat<(i64 (ctpop (i64 (zexti32 (i64 GPR:$rs1))))), (CPOPW GPR:$rs1)>;
582 def : Pat<(i64 (riscv_absw GPR:$rs1)),
583 (MAX GPR:$rs1, (XLenVT (SUBW (XLenVT X0), GPR:$rs1)))>;
584 } // Predicates = [HasStdExtZbb, IsRV64]
586 let Predicates = [HasStdExtZbb] in {
587 def : Pat<(XLenVT (sext_inreg GPR:$rs1, i8)), (SEXT_B GPR:$rs1)>;
588 def : Pat<(XLenVT (sext_inreg GPR:$rs1, i16)), (SEXT_H GPR:$rs1)>;
589 } // Predicates = [HasStdExtZbb]
591 let Predicates = [HasStdExtZbb] in {
592 def : PatGprGpr<smin, MIN>;
593 def : PatGprGpr<smax, MAX>;
594 def : PatGprGpr<umin, MINU>;
595 def : PatGprGpr<umax, MAXU>;
596 } // Predicates = [HasStdExtZbb]
598 let Predicates = [HasStdExtZbbOrZbkb, IsRV32] in
599 def : PatGpr<bswap, REV8_RV32, i32>;
601 let Predicates = [HasStdExtZbbOrZbkb, IsRV64] in
602 def : PatGpr<bswap, REV8_RV64, i64>;
604 let Predicates = [HasStdExtZbkb] in {
605 def : Pat<(or (and (shl GPR:$rs2, (XLenVT 8)), 0xFFFF),
606 (zexti8 (XLenVT GPR:$rs1))),
607 (PACKH GPR:$rs1, GPR:$rs2)>;
608 def : Pat<(or (shl (zexti8 (XLenVT GPR:$rs2)), (XLenVT 8)),
609 (zexti8 (XLenVT GPR:$rs1))),
610 (PACKH GPR:$rs1, GPR:$rs2)>;
611 def : Pat<(and (or (shl GPR:$rs2, (XLenVT 8)),
612 (zexti8 (XLenVT GPR:$rs1))), 0xFFFF),
613 (PACKH GPR:$rs1, GPR:$rs2)>;
614 def : 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))>;
618 def : Pat<(binop_allhusers<or> (shl GPR:$rs2, (XLenVT 8)),
619 (zexti8 (XLenVT GPR:$rs1))),
620 (PACKH GPR:$rs1, GPR:$rs2)>;
621 } // Predicates = [HasStdExtZbkb]
623 let Predicates = [HasStdExtZbkb, IsRV32] in {
624 def : Pat<(i32 (or (zexti16 (i32 GPR:$rs1)), (shl GPR:$rs2, (i32 16)))),
625 (PACK GPR:$rs1, GPR:$rs2)>;
627 (shl (zexti8 (XLenVT GPR:$op1rs2)), (XLenVT 24)),
628 (shl (zexti8 (XLenVT GPR:$op1rs1)), (XLenVT 16))),
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)))>;
636 let Predicates = [HasStdExtZbkb, IsRV64] in {
637 def : Pat<(i64 (or (zexti32 (i64 GPR:$rs1)), (shl GPR:$rs2, (i64 32)))),
638 (PACK GPR:$rs1, GPR:$rs2)>;
640 def : Pat<(binop_allwusers<or> (shl GPR:$rs2, (i64 16)),
641 (zexti16 (i64 GPR:$rs1))),
642 (PACKW GPR:$rs1, GPR:$rs2)>;
643 def : 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]
648 let Predicates = [HasStdExtZbb, IsRV32] in
649 def : Pat<(i32 (and GPR:$rs, 0xFFFF)), (ZEXT_H_RV32 GPR:$rs)>;
650 let Predicates = [HasStdExtZbb, IsRV64] in
651 def : Pat<(i64 (and GPR:$rs, 0xFFFF)), (ZEXT_H_RV64 GPR:$rs)>;
653 let Predicates = [HasStdExtZbkb, NoStdExtZbb, IsRV32] in
654 def : Pat<(i32 (and GPR:$rs, 0xFFFF)), (PACK GPR:$rs, (XLenVT X0))>;
655 let Predicates = [HasStdExtZbkb, NoStdExtZbb, IsRV64] in
656 def : Pat<(i64 (and GPR:$rs, 0xFFFF)), (PACKW GPR:$rs, (XLenVT X0))>;
658 let Predicates = [HasStdExtZba] in {
660 foreach 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)>;
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)>;
673 def : Pat<(add_like (XLenVT GPR:$r), CSImm12MulBy4:$i),
674 (SH2ADD (XLenVT (ADDI (XLenVT X0), CSImm12MulBy4:$i)),
676 def : Pat<(add_like (XLenVT GPR:$r), CSImm12MulBy8:$i),
677 (SH3ADD (XLenVT (ADDI (XLenVT X0), CSImm12MulBy8:$i)),
680 } // Predicates = [HasStdExtZba]
682 let Predicates = [HasStdExtZba, IsRV64] in {
683 def : 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
687 def : Pat<(i64 (and GPR:$rs1, Shifted32OnesMask:$mask)),
688 (SLLI_UW (XLenVT (SRLI GPR:$rs1, Shifted32OnesMask:$mask)),
689 Shifted32OnesMask:$mask)>;
690 def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0xFFFFFFFF), GPR:$rs2)),
691 (ADD_UW GPR:$rs1, GPR:$rs2)>;
692 def : Pat<(i64 (and GPR:$rs, 0xFFFFFFFF)), (ADD_UW GPR:$rs, (XLenVT X0))>;
694 foreach 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)>;
702 def : Pat<(i64 (add_like_non_imm12 (and (shl GPR:$rs1, (i64 1)), 0x1FFFFFFFF), (XLenVT GPR:$rs2))),
703 (SH1ADD_UW GPR:$rs1, GPR:$rs2)>;
704 def : Pat<(i64 (add_like_non_imm12 (and (shl GPR:$rs1, (i64 2)), 0x3FFFFFFFF), (XLenVT GPR:$rs2))),
705 (SH2ADD_UW GPR:$rs1, GPR:$rs2)>;
706 def : Pat<(i64 (add_like_non_imm12 (and (shl GPR:$rs1, (i64 3)), 0x7FFFFFFFF), (XLenVT GPR:$rs2))),
707 (SH3ADD_UW GPR:$rs1, GPR:$rs2)>;
709 // More complex cases use a ComplexPattern.
710 foreach 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)>;
716 def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0xFFFFFFFE), (XLenVT GPR:$rs2))),
717 (SH1ADD (XLenVT (SRLIW GPR:$rs1, 1)), GPR:$rs2)>;
718 def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0xFFFFFFFC), (XLenVT GPR:$rs2))),
719 (SH2ADD (XLenVT (SRLIW GPR:$rs1, 2)), GPR:$rs2)>;
720 def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0xFFFFFFF8), (XLenVT GPR:$rs2))),
721 (SH3ADD (XLenVT (SRLIW GPR:$rs1, 3)), GPR:$rs2)>;
723 // Use SRLI to clear the LSBs and SHXADD_UW to mask and shift.
724 def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0x1FFFFFFFE), (XLenVT GPR:$rs2))),
725 (SH1ADD_UW (XLenVT (SRLI GPR:$rs1, 1)), GPR:$rs2)>;
726 def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0x3FFFFFFFC), (XLenVT GPR:$rs2))),
727 (SH2ADD_UW (XLenVT (SRLI GPR:$rs1, 2)), GPR:$rs2)>;
728 def : Pat<(i64 (add_like_non_imm12 (and GPR:$rs1, 0x7FFFFFFF8), (XLenVT GPR:$rs2))),
729 (SH3ADD_UW (XLenVT (SRLI GPR:$rs1, 3)), GPR:$rs2)>;
731 } // Predicates = [HasStdExtZba, IsRV64]
733 let Predicates = [HasStdExtZbcOrZbkc] in {
734 def : PatGprGpr<riscv_clmul, CLMUL>;
735 def : PatGprGpr<riscv_clmulh, CLMULH>;
736 } // Predicates = [HasStdExtZbcOrZbkc]
738 let Predicates = [HasStdExtZbc] in
739 def : PatGprGpr<riscv_clmulr, CLMULR>;
741 let Predicates = [HasStdExtZbkx] in {
742 def : PatGprGpr<int_riscv_xperm4, XPERM4>;
743 def : PatGprGpr<int_riscv_xperm8, XPERM8>;
744 } // Predicates = [HasStdExtZbkx]