//===-- RISCVInstrInfoZb.td - RISC-V Bitmanip instructions -*- tablegen -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file describes the RISC-V instructions from the standard Bitmanip // extensions, versions: // Zba - 1.0 // Zbb - 1.0 // Zbc - 1.0 // Zbs - 1.0 // Zbe - 0.93 *experimental // Zbf - 0.93 *experimental // Zbm - 0.93 *experimental // Zbp - 0.93 *experimental // Zbr - 0.93 *experimental // Zbt - 0.93 *experimental // // The experimental extensions appeared in an earlier draft of the Bitmanip // extensions. They are not ratified and subject to change. // // This file also describes RISC-V instructions from the Zbk* extensions in // Cryptography Extensions Volume I: Scalar & Entropy Source Instructions, // versions: // Zbkb - 1.0 // Zbkc - 1.0 // Zbkx - 1.0 // //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // Operand and SDNode transformation definitions. //===----------------------------------------------------------------------===// def riscv_clzw : SDNode<"RISCVISD::CLZW", SDT_RISCVIntUnaryOpW>; def riscv_ctzw : SDNode<"RISCVISD::CTZW", SDT_RISCVIntUnaryOpW>; def riscv_rolw : SDNode<"RISCVISD::ROLW", SDT_RISCVIntBinOpW>; def riscv_rorw : SDNode<"RISCVISD::RORW", SDT_RISCVIntBinOpW>; def riscv_fslw : SDNode<"RISCVISD::FSLW", SDT_RISCVIntShiftDOpW>; def riscv_fsrw : SDNode<"RISCVISD::FSRW", SDT_RISCVIntShiftDOpW>; def riscv_fsl : SDNode<"RISCVISD::FSL", SDTIntShiftDOp>; def riscv_fsr : SDNode<"RISCVISD::FSR", SDTIntShiftDOp>; def riscv_grev : SDNode<"RISCVISD::GREV", SDTIntBinOp>; def riscv_grevw : SDNode<"RISCVISD::GREVW", SDT_RISCVIntBinOpW>; def riscv_gorc : SDNode<"RISCVISD::GORC", SDTIntBinOp>; def riscv_gorcw : SDNode<"RISCVISD::GORCW", SDT_RISCVIntBinOpW>; def riscv_shfl : SDNode<"RISCVISD::SHFL", SDTIntBinOp>; def riscv_shflw : SDNode<"RISCVISD::SHFLW", SDT_RISCVIntBinOpW>; def riscv_unshfl : SDNode<"RISCVISD::UNSHFL", SDTIntBinOp>; def riscv_unshflw: SDNode<"RISCVISD::UNSHFLW",SDT_RISCVIntBinOpW>; def riscv_bfp : SDNode<"RISCVISD::BFP", SDTIntBinOp>; def riscv_bfpw : SDNode<"RISCVISD::BFPW", SDT_RISCVIntBinOpW>; def riscv_bcompress : SDNode<"RISCVISD::BCOMPRESS", SDTIntBinOp>; def riscv_bcompressw : SDNode<"RISCVISD::BCOMPRESSW", SDT_RISCVIntBinOpW>; def riscv_bdecompress : SDNode<"RISCVISD::BDECOMPRESS", SDTIntBinOp>; def riscv_bdecompressw : SDNode<"RISCVISD::BDECOMPRESSW",SDT_RISCVIntBinOpW>; def UImmLog2XLenHalfAsmOperand : AsmOperandClass { let Name = "UImmLog2XLenHalf"; let RenderMethod = "addImmOperands"; let DiagnosticType = "InvalidUImmLog2XLenHalf"; } def shfl_uimm : Operand<XLenVT>, ImmLeaf<XLenVT, [{ if (Subtarget->is64Bit()) return isUInt<5>(Imm); return isUInt<4>(Imm); }]> { let ParserMatchClass = UImmLog2XLenHalfAsmOperand; let DecoderMethod = "decodeUImmOperand<5>"; let MCOperandPredicate = [{ int64_t Imm; if (!MCOp.evaluateAsConstantImm(Imm)) return false; if (STI.getTargetTriple().isArch64Bit()) return isUInt<5>(Imm); return isUInt<4>(Imm); }]; } def BCLRXForm : SDNodeXForm<imm, [{ // Find the lowest 0. return CurDAG->getTargetConstant(countTrailingOnes(N->getZExtValue()), SDLoc(N), N->getValueType(0)); }]>; def BSETINVXForm : SDNodeXForm<imm, [{ // Find the lowest 1. return CurDAG->getTargetConstant(countTrailingZeros(N->getZExtValue()), SDLoc(N), N->getValueType(0)); }]>; // Checks if this mask has a single 0 bit and cannot be used with ANDI. def BCLRMask : ImmLeaf<XLenVT, [{ if (Subtarget->is64Bit()) return !isInt<12>(Imm) && isPowerOf2_64(~Imm); return !isInt<12>(Imm) && isPowerOf2_32(~Imm); }], BCLRXForm>; // Checks if this mask has a single 1 bit and cannot be used with ORI/XORI. def BSETINVMask : ImmLeaf<XLenVT, [{ if (Subtarget->is64Bit()) return !isInt<12>(Imm) && isPowerOf2_64(Imm); return !isInt<12>(Imm) && isPowerOf2_32(Imm); }], BSETINVXForm>; // Check if (or r, i) can be optimized to (BSETI (BSETI r, i0), i1), // in which i = (1 << i0) | (1 << i1). def BSETINVTwoBitsMask : PatLeaf<(imm), [{ if (!N->hasOneUse()) return false; // The immediate should not be a simm12. if (isInt<12>(N->getSExtValue())) return false; // The immediate must have exactly two bits set. return countPopulation(N->getZExtValue()) == 2; }]>; def TrailingZerosXForm : SDNodeXForm<imm, [{ uint64_t I = N->getZExtValue(); return CurDAG->getTargetConstant(countTrailingZeros(I), SDLoc(N), N->getValueType(0)); }]>; def BSETINVTwoBitsMaskHigh : SDNodeXForm<imm, [{ uint64_t I = N->getZExtValue(); return CurDAG->getTargetConstant(63 - countLeadingZeros(I), SDLoc(N), N->getValueType(0)); }]>; // Check if (or r, imm) can be optimized to (BSETI (ORI r, i0), i1), // in which imm = i0 | (1 << i1). def BSETINVORIMask : PatLeaf<(imm), [{ if (!N->hasOneUse()) return false; // The immediate should not be a simm12. if (isInt<12>(N->getSExtValue())) return false; // There should be only one set bit from bit 11 to the top. return isPowerOf2_64(N->getZExtValue() & ~0x7ff); }]>; def BSETINVORIMaskLow : SDNodeXForm<imm, [{ return CurDAG->getTargetConstant(N->getZExtValue() & 0x7ff, SDLoc(N), N->getValueType(0)); }]>; // Check if (and r, i) can be optimized to (BCLRI (BCLRI r, i0), i1), // in which i = ~((1<<i0) | (1<<i1)). def BCLRITwoBitsMask : PatLeaf<(imm), [{ if (!N->hasOneUse()) return false; // The immediate should not be a simm12. if (isInt<12>(N->getSExtValue())) return false; // The immediate must have exactly two bits clear. return countPopulation(N->getZExtValue()) == Subtarget->getXLen() - 2; }]>; def BCLRITwoBitsMaskLow : SDNodeXForm<imm, [{ return CurDAG->getTargetConstant(countTrailingZeros(~N->getZExtValue()), SDLoc(N), N->getValueType(0)); }]>; def BCLRITwoBitsMaskHigh : SDNodeXForm<imm, [{ uint64_t I = N->getSExtValue(); if (!Subtarget->is64Bit()) I |= 0xffffffffull << 32; return CurDAG->getTargetConstant(63 - countLeadingZeros(~I), SDLoc(N), N->getValueType(0)); }]>; // Check if (and r, i) can be optimized to (BCLRI (ANDI r, i0), i1), // in which i = i0 & ~(1<<i1). def BCLRIANDIMask : PatLeaf<(imm), [{ if (!N->hasOneUse()) return false; // The immediate should not be a simm12. if (isInt<12>(N->getSExtValue())) return false; // There should be only one clear bit from bit 11 to the top. uint64_t I = N->getZExtValue() | 0x7ff; return Subtarget->is64Bit() ? isPowerOf2_64(~I) : isPowerOf2_32(~I); }]>; def BCLRIANDIMaskLow : SDNodeXForm<imm, [{ return CurDAG->getTargetConstant((N->getZExtValue() & 0x7ff) | ~0x7ffull, SDLoc(N), N->getValueType(0)); }]>; def C3LeftShift : PatLeaf<(imm), [{ uint64_t C = N->getZExtValue(); return C > 3 && ((C % 3) == 0) && isPowerOf2_64(C / 3); }]>; def C5LeftShift : PatLeaf<(imm), [{ uint64_t C = N->getZExtValue(); return C > 5 && ((C % 5) == 0) && isPowerOf2_64(C / 5); }]>; def C9LeftShift : PatLeaf<(imm), [{ uint64_t C = N->getZExtValue(); return C > 9 && ((C % 9) == 0) && isPowerOf2_64(C / 9); }]>; def CSImm12MulBy4 : PatLeaf<(imm), [{ if (!N->hasOneUse()) return false; int64_t C = N->getSExtValue(); // Skip if C is simm12 or can be optimized by the PatLeaf AddiPair. return !isInt<13>(C) && isShiftedInt<12, 2>(C); }]>; def CSImm12MulBy8 : PatLeaf<(imm), [{ if (!N->hasOneUse()) return false; int64_t C = N->getSExtValue(); // Skip if C is simm12 or can be optimized by the PatLeaf AddiPair or // CSImm12MulBy4. return !isInt<14>(C) && isShiftedInt<12, 3>(C); }]>; def SimmShiftRightBy2XForm : SDNodeXForm<imm, [{ return CurDAG->getTargetConstant(N->getSExtValue() >> 2, SDLoc(N), N->getValueType(0)); }]>; def SimmShiftRightBy3XForm : SDNodeXForm<imm, [{ return CurDAG->getTargetConstant(N->getSExtValue() >> 3, SDLoc(N), N->getValueType(0)); }]>; // Pattern to exclude simm12 immediates from matching. def non_imm12 : PatLeaf<(XLenVT GPR:$a), [{ auto *C = dyn_cast<ConstantSDNode>(N); return !C || !isInt<12>(C->getSExtValue()); }]>; def sh1add_op : ComplexPattern<XLenVT, 1, "selectSH1ADDOp", [], [], 6>; def sh2add_op : ComplexPattern<XLenVT, 1, "selectSH2ADDOp", [], [], 6>; def sh3add_op : ComplexPattern<XLenVT, 1, "selectSH3ADDOp", [], [], 6>; //===----------------------------------------------------------------------===// // Instruction class templates //===----------------------------------------------------------------------===// // Some of these templates should be moved to RISCVInstrFormats.td once the B // extension has been ratified. let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class RVBUnary<bits<7> funct7, bits<5> funct5, bits<3> funct3, RISCVOpcode opcode, string opcodestr> : RVInstR<funct7, funct3, opcode, (outs GPR:$rd), (ins GPR:$rs1), opcodestr, "$rd, $rs1"> { let rs2 = funct5; } let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class RVBShift_ri<bits<5> imm11_7, bits<3> funct3, RISCVOpcode opcode, string opcodestr> : RVInstIShift<imm11_7, funct3, opcode, (outs GPR:$rd), (ins GPR:$rs1, uimmlog2xlen:$shamt), opcodestr, "$rd, $rs1, $shamt">; let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class RVBShiftW_ri<bits<7> imm11_5, bits<3> funct3, RISCVOpcode opcode, string opcodestr> : RVInstIShiftW<imm11_5, funct3, opcode, (outs GPR:$rd), (ins GPR:$rs1, uimm5:$shamt), opcodestr, "$rd, $rs1, $shamt">; // Using RVInstIShiftW since it allocates 5 bits instead of 6 to shamt. let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class RVBShfl_ri<bits<7> imm11_5, bits<3> funct3, RISCVOpcode opcode, string opcodestr> : RVInstIShiftW<imm11_5, funct3, opcode, (outs GPR:$rd), (ins GPR:$rs1, shfl_uimm:$shamt), opcodestr, "$rd, $rs1, $shamt">; let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class RVBTernaryR<bits<2> funct2, bits<3> funct3, RISCVOpcode opcode, string opcodestr, string argstr> : RVInstR4<funct2, funct3, opcode, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2, GPR:$rs3), opcodestr, argstr>; // Currently used by FSRI only let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class RVBTernaryImm6<bits<3> funct3, RISCVOpcode opcode, string opcodestr, string argstr> : RVInst<(outs GPR:$rd), (ins GPR:$rs1, GPR:$rs3, uimmlog2xlen:$shamt), opcodestr, argstr, [], InstFormatR4> { bits<5> rs3; bits<6> shamt; bits<5> rs1; bits<5> rd; let Inst{31-27} = rs3; let Inst{26} = 1; let Inst{25-20} = shamt; let Inst{19-15} = rs1; let Inst{14-12} = funct3; let Inst{11-7} = rd; let Opcode = opcode.Value; } // Currently used by FSRIW only let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class RVBTernaryImm5<bits<2> funct2, bits<3> funct3, RISCVOpcode opcode, string opcodestr, string argstr> : RVInst<(outs GPR:$rd), (ins GPR:$rs1, GPR:$rs3, uimm5:$shamt), opcodestr, argstr, [], InstFormatR4> { bits<5> rs3; bits<5> shamt; bits<5> rs1; bits<5> rd; let Inst{31-27} = rs3; let Inst{26-25} = funct2; let Inst{24-20} = shamt; let Inst{19-15} = rs1; let Inst{14-12} = funct3; let Inst{11-7} = rd; let Opcode = opcode.Value; } //===----------------------------------------------------------------------===// // Instructions //===----------------------------------------------------------------------===// let Predicates = [HasStdExtZbbOrZbpOrZbkb] in { def ANDN : ALU_rr<0b0100000, 0b111, "andn">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; def ORN : ALU_rr<0b0100000, 0b110, "orn">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; def XNOR : ALU_rr<0b0100000, 0b100, "xnor">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; } // Predicates = [HasStdExtZbbOrZbpOrZbkb] let Predicates = [HasStdExtZba] in { def SH1ADD : ALU_rr<0b0010000, 0b010, "sh1add">, Sched<[WriteSHXADD, ReadSHXADD, ReadSHXADD]>; def SH2ADD : ALU_rr<0b0010000, 0b100, "sh2add">, Sched<[WriteSHXADD, ReadSHXADD, ReadSHXADD]>; def SH3ADD : ALU_rr<0b0010000, 0b110, "sh3add">, Sched<[WriteSHXADD, ReadSHXADD, ReadSHXADD]>; } // Predicates = [HasStdExtZba] let Predicates = [HasStdExtZba, IsRV64] in { def SLLI_UW : RVBShift_ri<0b00001, 0b001, OPC_OP_IMM_32, "slli.uw">, Sched<[WriteShiftImm32, ReadShiftImm32]>; def ADD_UW : ALUW_rr<0b0000100, 0b000, "add.uw">, Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; def SH1ADD_UW : ALUW_rr<0b0010000, 0b010, "sh1add.uw">, Sched<[WriteSHXADD32, ReadSHXADD32, ReadSHXADD32]>; def SH2ADD_UW : ALUW_rr<0b0010000, 0b100, "sh2add.uw">, Sched<[WriteSHXADD32, ReadSHXADD32, ReadSHXADD32]>; def SH3ADD_UW : ALUW_rr<0b0010000, 0b110, "sh3add.uw">, Sched<[WriteSHXADD32, ReadSHXADD32, ReadSHXADD32]>; } // Predicates = [HasStdExtZba, IsRV64] let Predicates = [HasStdExtZbbOrZbpOrZbkb] in { def ROL : ALU_rr<0b0110000, 0b001, "rol">, Sched<[WriteRotateReg, ReadRotateReg, ReadRotateReg]>; def ROR : ALU_rr<0b0110000, 0b101, "ror">, Sched<[WriteRotateReg, ReadRotateReg, ReadRotateReg]>; def RORI : RVBShift_ri<0b01100, 0b101, OPC_OP_IMM, "rori">, Sched<[WriteRotateImm, ReadRotateImm]>; } // Predicates = [HasStdExtZbbOrZbpOrZbkb] let Predicates = [HasStdExtZbbOrZbpOrZbkb, IsRV64] in { def ROLW : ALUW_rr<0b0110000, 0b001, "rolw">, Sched<[WriteRotateReg32, ReadRotateReg32, ReadRotateReg32]>; def RORW : ALUW_rr<0b0110000, 0b101, "rorw">, Sched<[WriteRotateReg32, ReadRotateReg32, ReadRotateReg32]>; def RORIW : RVBShiftW_ri<0b0110000, 0b101, OPC_OP_IMM_32, "roriw">, Sched<[WriteRotateImm32, ReadRotateImm32]>; } // Predicates = [HasStdExtZbbOrZbpOrZbkb, IsRV64] let Predicates = [HasStdExtZbs] in { def BCLR : ALU_rr<0b0100100, 0b001, "bclr">, Sched<[WriteSingleBit, ReadSingleBit, ReadSingleBit]>; def BSET : ALU_rr<0b0010100, 0b001, "bset">, Sched<[WriteSingleBit, ReadSingleBit, ReadSingleBit]>; def BINV : ALU_rr<0b0110100, 0b001, "binv">, Sched<[WriteSingleBit, ReadSingleBit, ReadSingleBit]>; def BEXT : ALU_rr<0b0100100, 0b101, "bext">, Sched<[WriteSingleBit, ReadSingleBit, ReadSingleBit]>; def BCLRI : RVBShift_ri<0b01001, 0b001, OPC_OP_IMM, "bclri">, Sched<[WriteSingleBitImm, ReadSingleBitImm]>; def BSETI : RVBShift_ri<0b00101, 0b001, OPC_OP_IMM, "bseti">, Sched<[WriteSingleBitImm, ReadSingleBitImm]>; def BINVI : RVBShift_ri<0b01101, 0b001, OPC_OP_IMM, "binvi">, Sched<[WriteSingleBitImm, ReadSingleBitImm]>; def BEXTI : RVBShift_ri<0b01001, 0b101, OPC_OP_IMM, "bexti">, Sched<[WriteSingleBitImm, ReadSingleBitImm]>; } // Predicates = [HasStdExtZbs] let Predicates = [HasStdExtZbp] in { def GORC : ALU_rr<0b0010100, 0b101, "gorc">, Sched<[WriteORC, ReadORC, ReadORC]>; def GREV : ALU_rr<0b0110100, 0b101, "grev">, Sched<[WriteREV, ReadREV, ReadREV]>; def GREVI : RVBShift_ri<0b01101, 0b101, OPC_OP_IMM, "grevi">, Sched<[WriteREVImm, ReadREVImm]>; def GORCI : RVBShift_ri<0b00101, 0b101, OPC_OP_IMM, "gorci">, Sched<[WriteORCImm, ReadORCImm]>; def SHFL : ALU_rr<0b0000100, 0b001, "shfl">, Sched<[WriteSHFL, ReadSHFL, ReadSHFL]>; def UNSHFL : ALU_rr<0b0000100, 0b101, "unshfl">, Sched<[WriteUNSHFL, ReadUNSHFL, ReadUNSHFL]>; def SHFLI : RVBShfl_ri<0b0000100, 0b001, OPC_OP_IMM, "shfli">, Sched<[WriteSHFLImm, ReadSHFLImm]>; def UNSHFLI : RVBShfl_ri<0b0000100, 0b101, OPC_OP_IMM, "unshfli">, Sched<[WriteUNSHFLImm, ReadUNSHFLImm]>; def XPERM_H : ALU_rr<0b0010100, 0b110, "xperm.h">, Sched<[WriteXPERMH, ReadXPERMH, ReadXPERMH]>; } // Predicates = [HasStdExtZbp] let Predicates = [HasStdExtZbp, IsRV64] in { def GORCW : ALUW_rr<0b0010100, 0b101, "gorcw">, Sched<[WriteORC32, ReadORC32, ReadORC32]>; def GREVW : ALUW_rr<0b0110100, 0b101, "grevw">, Sched<[WriteREV32, ReadREV32, ReadREV32]>; def GORCIW : RVBShiftW_ri<0b0010100, 0b101, OPC_OP_IMM_32, "gorciw">, Sched<[WriteREVImm32, ReadREVImm32]>; def GREVIW : RVBShiftW_ri<0b0110100, 0b101, OPC_OP_IMM_32, "greviw">, Sched<[WriteORCImm32, ReadORCImm32]>; def SHFLW : ALUW_rr<0b0000100, 0b001, "shflw">, Sched<[WriteSHFL32, ReadSHFL32, ReadSHFL32]>; def UNSHFLW : ALUW_rr<0b0000100, 0b101, "unshflw">, Sched<[WriteUNSHFL32, ReadUNSHFL32, ReadUNSHFL32]>; def XPERM_W : ALU_rr<0b0010100, 0b000, "xperm.w">, Sched<[WriteXPERMW, ReadXPERMW, ReadXPERMW]>; } // Predicates = [HasStdExtZbp, IsRV64] // These instructions were named xperm.n and xperm.b in the last version of // the draft bit manipulation specification they were included in. However, we // use the mnemonics given to them in the ratified Zbkx extension. let Predicates = [HasStdExtZbpOrZbkx] in { def XPERM4 : ALU_rr<0b0010100, 0b010, "xperm4">, Sched<[]>; def XPERM8 : ALU_rr<0b0010100, 0b100, "xperm8">, Sched<[]>; } // Predicates = [HasStdExtZbpOrZbkx] let Predicates = [HasStdExtZbt] in { def CMIX : RVBTernaryR<0b11, 0b001, OPC_OP, "cmix", "$rd, $rs2, $rs1, $rs3">, Sched<[WriteCMix, ReadCMix, ReadCMix, ReadCMix]>; def CMOV : RVBTernaryR<0b11, 0b101, OPC_OP, "cmov", "$rd, $rs2, $rs1, $rs3">, Sched<[WriteCMov, ReadCMov, ReadCMov, ReadCMov]>; def FSL : RVBTernaryR<0b10, 0b001, OPC_OP, "fsl", "$rd, $rs1, $rs3, $rs2">, Sched<[WriteFSReg, ReadFSReg, ReadFSReg, ReadFSReg]>; def FSR : RVBTernaryR<0b10, 0b101, OPC_OP, "fsr", "$rd, $rs1, $rs3, $rs2">, Sched<[WriteFSReg, ReadFSReg, ReadFSReg, ReadFSReg]>; def FSRI : RVBTernaryImm6<0b101, OPC_OP_IMM, "fsri", "$rd, $rs1, $rs3, $shamt">, Sched<[WriteFSRImm, ReadFSRImm, ReadFSRImm]>; } // Predicates = [HasStdExtZbt] let Predicates = [HasStdExtZbt, IsRV64] in { def FSLW : RVBTernaryR<0b10, 0b001, OPC_OP_32, "fslw", "$rd, $rs1, $rs3, $rs2">, Sched<[WriteFSReg32, ReadFSReg32, ReadFSReg32, ReadFSReg32]>; def FSRW : RVBTernaryR<0b10, 0b101, OPC_OP_32, "fsrw", "$rd, $rs1, $rs3, $rs2">, Sched<[WriteFSReg32, ReadFSReg32, ReadFSReg32, ReadFSReg32]>; def FSRIW : RVBTernaryImm5<0b10, 0b101, OPC_OP_IMM_32, "fsriw", "$rd, $rs1, $rs3, $shamt">, Sched<[WriteFSRImm32, ReadFSRImm32, ReadFSRImm32]>; } // Predicates = [HasStdExtZbt, IsRV64] let Predicates = [HasStdExtZbb] in { def CLZ : RVBUnary<0b0110000, 0b00000, 0b001, OPC_OP_IMM, "clz">, Sched<[WriteCLZ, ReadCLZ]>; def CTZ : RVBUnary<0b0110000, 0b00001, 0b001, OPC_OP_IMM, "ctz">, Sched<[WriteCTZ, ReadCTZ]>; def CPOP : RVBUnary<0b0110000, 0b00010, 0b001, OPC_OP_IMM, "cpop">, Sched<[WriteCPOP, ReadCPOP]>; } // Predicates = [HasStdExtZbb] let Predicates = [HasStdExtZbb, IsRV64] in { def CLZW : RVBUnary<0b0110000, 0b00000, 0b001, OPC_OP_IMM_32, "clzw">, Sched<[WriteCLZ32, ReadCLZ32]>; def CTZW : RVBUnary<0b0110000, 0b00001, 0b001, OPC_OP_IMM_32, "ctzw">, Sched<[WriteCTZ32, ReadCTZ32]>; def CPOPW : RVBUnary<0b0110000, 0b00010, 0b001, OPC_OP_IMM_32, "cpopw">, Sched<[WriteCPOP32, ReadCPOP32]>; } // Predicates = [HasStdExtZbb, IsRV64] let Predicates = [HasStdExtZbb] in { def SEXT_B : RVBUnary<0b0110000, 0b00100, 0b001, OPC_OP_IMM, "sext.b">, Sched<[WriteIALU, ReadIALU]>; def SEXT_H : RVBUnary<0b0110000, 0b00101, 0b001, OPC_OP_IMM, "sext.h">, Sched<[WriteIALU, ReadIALU]>; } // Predicates = [HasStdExtZbb] let Predicates = [HasStdExtZbr] in { def CRC32_B : RVBUnary<0b0110000, 0b10000, 0b001, OPC_OP_IMM, "crc32.b">, Sched<[WriteCRCB, ReadCRCB]>; def CRC32_H : RVBUnary<0b0110000, 0b10001, 0b001, OPC_OP_IMM, "crc32.h">, Sched<[WriteCRCH, ReadCRCH]>; def CRC32_W : RVBUnary<0b0110000, 0b10010, 0b001, OPC_OP_IMM, "crc32.w">, Sched<[WriteCRCW, ReadCRCW]>; def CRC32C_B : RVBUnary<0b0110000, 0b11000, 0b001, OPC_OP_IMM, "crc32c.b">, Sched<[WriteCRCCB, ReadCRCCB]>; def CRC32C_H : RVBUnary<0b0110000, 0b11001, 0b001, OPC_OP_IMM, "crc32c.h">, Sched<[WriteCRCCH, ReadCRCCH]>; def CRC32C_W : RVBUnary<0b0110000, 0b11010, 0b001, OPC_OP_IMM, "crc32c.w">, Sched<[WriteCRCCW, ReadCRCCW]>; } // Predicates = [HasStdExtZbr] let Predicates = [HasStdExtZbr, IsRV64] in { def CRC32_D : RVBUnary<0b0110000, 0b10011, 0b001, OPC_OP_IMM, "crc32.d">, Sched<[WriteCRCD, ReadCRCD]>; def CRC32C_D : RVBUnary<0b0110000, 0b11011, 0b001, OPC_OP_IMM, "crc32c.d">, Sched<[WriteCRCCD, ReadCRCCD]>; } // Predicates = [HasStdExtZbr, IsRV64] let Predicates = [HasStdExtZbc] in { def CLMULR : ALU_rr<0b0000101, 0b010, "clmulr", /*Commutable*/1>, Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>; } // Predicates = [HasStdExtZbc] let Predicates = [HasStdExtZbcOrZbkc] in { def CLMUL : ALU_rr<0b0000101, 0b001, "clmul", /*Commutable*/1>, Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>; def CLMULH : ALU_rr<0b0000101, 0b011, "clmulh", /*Commutable*/1>, Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>; } // Predicates = [HasStdExtZbcOrZbkc] let Predicates = [HasStdExtZbb] in { def MIN : ALU_rr<0b0000101, 0b100, "min", /*Commutable*/1>, Sched<[WriteIALU, ReadIALU, ReadIALU]>; def MINU : ALU_rr<0b0000101, 0b101, "minu", /*Commutable*/1>, Sched<[WriteIALU, ReadIALU, ReadIALU]>; def MAX : ALU_rr<0b0000101, 0b110, "max", /*Commutable*/1>, Sched<[WriteIALU, ReadIALU, ReadIALU]>; def MAXU : ALU_rr<0b0000101, 0b111, "maxu", /*Commutable*/1>, Sched<[WriteIALU, ReadIALU, ReadIALU]>; } // Predicates = [HasStdExtZbb] let Predicates = [HasStdExtZbe] in { // NOTE: These mnemonics are from the 0.94 spec. There is a name conflict with // bext in the 0.93 spec. def BDECOMPRESS : ALU_rr<0b0100100, 0b110, "bdecompress">, Sched<[WriteDecompress, ReadDecompress, ReadDecompress]>; def BCOMPRESS : ALU_rr<0b0000100, 0b110, "bcompress">, Sched<[WriteCompress, ReadCompress, ReadCompress]>; } // Predicates = [HasStdExtZbe] let Predicates = [HasStdExtZbe, IsRV64] in { // NOTE: These mnemonics are from the 0.94 spec. There is a name conflict with // bextw in the 0.93 spec. def BDECOMPRESSW : ALUW_rr<0b0100100, 0b110, "bdecompressw">, Sched<[WriteDecompress32, ReadDecompress32, ReadDecompress32]>; def BCOMPRESSW : ALUW_rr<0b0000100, 0b110, "bcompressw">, Sched<[WriteCompress32, ReadCompress32, ReadCompress32]>; } // Predicates = [HasStdExtZbe, IsRV64] let Predicates = [HasStdExtZbpOrZbkb] in { def PACK : ALU_rr<0b0000100, 0b100, "pack">, Sched<[WritePACK, ReadPACK, ReadPACK]>; def PACKH : ALU_rr<0b0000100, 0b111, "packh">, Sched<[WritePACK, ReadPACK, ReadPACK]>; } // Predicates = [HasStdExtZbpOrZbkb] let Predicates = [HasStdExtZbpOrZbkb, IsRV64] in def PACKW : ALUW_rr<0b0000100, 0b100, "packw">, Sched<[WritePACK32, ReadPACK32, ReadPACK32]>; let Predicates = [HasStdExtZbp] in def PACKU : ALU_rr<0b0100100, 0b100, "packu">, Sched<[WritePACKU, ReadPACKU, ReadPACKU]>; let Predicates = [HasStdExtZbp, IsRV64] in def PACKUW : ALUW_rr<0b0100100, 0b100, "packuw">, Sched<[WritePACKU32, ReadPACKU32, ReadPACKU32]>; let Predicates = [HasStdExtZbm, IsRV64] in { def BMATFLIP : RVBUnary<0b0110000, 0b00011, 0b001, OPC_OP_IMM, "bmatflip">, Sched<[WriteBMatrix, ReadBMatrix]>; def BMATOR : ALU_rr<0b0000100, 0b011, "bmator">, Sched<[WriteBMatrix, ReadBMatrix, ReadBMatrix]>; def BMATXOR : ALU_rr<0b0100100, 0b011, "bmatxor">, Sched<[WriteBMatrix, ReadBMatrix, ReadBMatrix]>; } // Predicates = [HasStdExtZbm, IsRV64] let Predicates = [HasStdExtZbf] in def BFP : ALU_rr<0b0100100, 0b111, "bfp">, Sched<[WriteBFP, ReadBFP, ReadBFP]>; let Predicates = [HasStdExtZbf, IsRV64] in def BFPW : ALUW_rr<0b0100100, 0b111, "bfpw">, Sched<[WriteBFP32, ReadBFP32, ReadBFP32]>; let Predicates = [HasStdExtZbbOrZbp, IsRV32] in { def ZEXT_H_RV32 : RVBUnary<0b0000100, 0b00000, 0b100, OPC_OP, "zext.h">, Sched<[WriteIALU, ReadIALU]>; } // Predicates = [HasStdExtZbbOrZbp, IsRV32] let Predicates = [HasStdExtZbbOrZbp, IsRV64] in { def ZEXT_H_RV64 : RVBUnary<0b0000100, 0b00000, 0b100, OPC_OP_32, "zext.h">, Sched<[WriteIALU, ReadIALU]>; } // Predicates = [HasStdExtZbbOrZbp, IsRV64] // We treat rev8 and orc.b as standalone instructions even though they use a // portion of the encodings for grevi and gorci. This allows us to support only // those encodings when only Zbb is enabled. We do this even when grevi and // gorci are available with Zbp. Trying to use 'HasStdExtZbb, NotHasStdExtZbp' // causes diagnostics to suggest that Zbp rather than Zbb is required for rev8 // or gorci. Since Zbb is closer to being finalized than Zbp this will be // misleading to users. let Predicates = [HasStdExtZbbOrZbpOrZbkb, IsRV32] in { def REV8_RV32 : RVBUnary<0b0110100, 0b11000, 0b101, OPC_OP_IMM, "rev8">, Sched<[WriteREV8, ReadREV8]>; } // Predicates = [HasStdExtZbbOrZbpOrZbkb, IsRV32] let Predicates = [HasStdExtZbbOrZbpOrZbkb, IsRV64] in { def REV8_RV64 : RVBUnary<0b0110101, 0b11000, 0b101, OPC_OP_IMM, "rev8">, Sched<[WriteREV8, ReadREV8]>; } // Predicates = [HasStdExtZbbOrZbpOrZbkb, IsRV64] let Predicates = [HasStdExtZbbOrZbp] in { def ORC_B : RVBUnary<0b0010100, 0b00111, 0b101, OPC_OP_IMM, "orc.b">, Sched<[WriteORCB, ReadORCB]>; } // Predicates = [HasStdExtZbbOrZbp] let Predicates = [HasStdExtZbpOrZbkb] in def BREV8 : RVBUnary<0b0110100, 0b00111, 0b101, OPC_OP_IMM, "brev8">, Sched<[]>; let Predicates = [HasStdExtZbpOrZbkb, IsRV32] in { def ZIP_RV32 : RVBUnary<0b0000100, 0b01111, 0b001, OPC_OP_IMM, "zip">, Sched<[]>; def UNZIP_RV32 : RVBUnary<0b0000100, 0b01111, 0b101, OPC_OP_IMM, "unzip">, Sched<[]>; } // Predicates = [HasStdExtZbpOrZbkb, IsRV32] //===----------------------------------------------------------------------===// // Pseudo Instructions //===----------------------------------------------------------------------===// let Predicates = [HasStdExtZba, IsRV64] in { def : InstAlias<"zext.w $rd, $rs", (ADD_UW GPR:$rd, GPR:$rs, X0)>; } // Predicates = [HasStdExtZba, IsRV64] let Predicates = [HasStdExtZbp] in { def : InstAlias<"rev.p $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b00001)>; def : InstAlias<"rev2.n $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b00010)>; def : InstAlias<"rev.n $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b00011)>; def : InstAlias<"rev4.b $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b00100)>; def : InstAlias<"rev2.b $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b00110)>; def : InstAlias<"rev8.h $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b01000)>; def : InstAlias<"rev4.h $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b01100)>; def : InstAlias<"rev2.h $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b01110)>; def : InstAlias<"rev.h $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b01111)>; def : InstAlias<"rev.b $rd, $rs", (BREV8 GPR:$rd, GPR:$rs)>; def : InstAlias<"zip.n $rd, $rs", (SHFLI GPR:$rd, GPR:$rs, 0b0001)>; def : InstAlias<"unzip.n $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b0001)>; def : InstAlias<"zip2.b $rd, $rs", (SHFLI GPR:$rd, GPR:$rs, 0b0010)>; def : InstAlias<"unzip2.b $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b0010)>; def : InstAlias<"zip.b $rd, $rs", (SHFLI GPR:$rd, GPR:$rs, 0b0011)>; def : InstAlias<"unzip.b $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b0011)>; def : InstAlias<"zip4.h $rd, $rs", (SHFLI GPR:$rd, GPR:$rs, 0b0100)>; def : InstAlias<"unzip4.h $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b0100)>; def : InstAlias<"zip2.h $rd, $rs", (SHFLI GPR:$rd, GPR:$rs, 0b0110)>; def : InstAlias<"unzip2.h $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b0110)>; def : InstAlias<"zip.h $rd, $rs", (SHFLI GPR:$rd, GPR:$rs, 0b0111)>; def : InstAlias<"unzip.h $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b0111)>; def : InstAlias<"orc.p $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b00001)>; def : InstAlias<"orc2.n $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b00010)>; def : InstAlias<"orc.n $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b00011)>; def : InstAlias<"orc4.b $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b00100)>; def : InstAlias<"orc2.b $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b00110)>; // orc.b is considered an instruction rather than an alias. def : InstAlias<"orc8.h $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b01000)>; def : InstAlias<"orc4.h $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b01100)>; def : InstAlias<"orc2.h $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b01110)>; def : InstAlias<"orc.h $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b01111)>; } // Predicates = [HasStdExtZbp] let Predicates = [HasStdExtZbp, IsRV32] in { def : InstAlias<"rev16 $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b10000)>; // rev8 is considered an instruction rather than an alias. def : InstAlias<"rev4 $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b11100)>; def : InstAlias<"rev2 $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b11110)>; def : InstAlias<"rev $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b11111)>; def : InstAlias<"zip8 $rd, $rs", (SHFLI GPR:$rd, GPR:$rs, 0b1000)>; def : InstAlias<"unzip8 $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b1000)>; def : InstAlias<"zip4 $rd, $rs", (SHFLI GPR:$rd, GPR:$rs, 0b1100)>; def : InstAlias<"unzip4 $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b1100)>; def : InstAlias<"zip2 $rd, $rs", (SHFLI GPR:$rd, GPR:$rs, 0b1110)>; def : InstAlias<"unzip2 $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b1110)>; // zip and unzip are considered instructions rather than an alias. def : InstAlias<"orc16 $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b10000)>; def : InstAlias<"orc8 $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b11000)>; def : InstAlias<"orc4 $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b11100)>; def : InstAlias<"orc2 $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b11110)>; def : InstAlias<"orc $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b11111)>; } // Predicates = [HasStdExtZbp, IsRV32] let Predicates = [HasStdExtZbp, IsRV64] in { def : InstAlias<"rev16.w $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b010000)>; def : InstAlias<"rev8.w $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b011000)>; def : InstAlias<"rev4.w $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b011100)>; def : InstAlias<"rev2.w $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b011110)>; def : InstAlias<"rev.w $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b011111)>; def : InstAlias<"rev32 $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b100000)>; def : InstAlias<"rev16 $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b110000)>; // rev8 is considered an instruction rather than an alias. def : InstAlias<"rev4 $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b111100)>; def : InstAlias<"rev2 $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b111110)>; def : InstAlias<"rev $rd, $rs", (GREVI GPR:$rd, GPR:$rs, 0b111111)>; def : InstAlias<"zip8.w $rd, $rs", (SHFLI GPR:$rd, GPR:$rs, 0b01000)>; def : InstAlias<"unzip8.w $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b01000)>; def : InstAlias<"zip4.w $rd, $rs", (SHFLI GPR:$rd, GPR:$rs, 0b01100)>; def : InstAlias<"unzip4.w $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b01100)>; def : InstAlias<"zip2.w $rd, $rs", (SHFLI GPR:$rd, GPR:$rs, 0b01110)>; def : InstAlias<"unzip2.w $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b01110)>; def : InstAlias<"zip.w $rd, $rs", (SHFLI GPR:$rd, GPR:$rs, 0b01111)>; def : InstAlias<"unzip.w $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b01111)>; def : InstAlias<"zip16 $rd, $rs", (SHFLI GPR:$rd, GPR:$rs, 0b10000)>; def : InstAlias<"unzip16 $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b10000)>; def : InstAlias<"zip8 $rd, $rs", (SHFLI GPR:$rd, GPR:$rs, 0b11000)>; def : InstAlias<"unzip8 $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b11000)>; def : InstAlias<"zip4 $rd, $rs", (SHFLI GPR:$rd, GPR:$rs, 0b11100)>; def : InstAlias<"unzip4 $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b11100)>; def : InstAlias<"zip2 $rd, $rs", (SHFLI GPR:$rd, GPR:$rs, 0b11110)>; def : InstAlias<"unzip2 $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b11110)>; def : InstAlias<"zip $rd, $rs", (SHFLI GPR:$rd, GPR:$rs, 0b11111)>; def : InstAlias<"unzip $rd, $rs", (UNSHFLI GPR:$rd, GPR:$rs, 0b11111)>; def : InstAlias<"orc16.w $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b010000)>; def : InstAlias<"orc8.w $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b011000)>; def : InstAlias<"orc4.w $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b011100)>; def : InstAlias<"orc2.w $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b011110)>; def : InstAlias<"orc.w $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b011111)>; def : InstAlias<"orc32 $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b100000)>; def : InstAlias<"orc16 $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b110000)>; def : InstAlias<"orc8 $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b111000)>; def : InstAlias<"orc4 $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b111100)>; def : InstAlias<"orc2 $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b111110)>; def : InstAlias<"orc $rd, $rs", (GORCI GPR:$rd, GPR:$rs, 0b111111)>; } // Predicates = [HasStdExtZbp, IsRV64] let Predicates = [HasStdExtZbbOrZbp] in { def : InstAlias<"ror $rd, $rs1, $shamt", (RORI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>; } // Predicates = [HasStdExtZbbOrZbp] let Predicates = [HasStdExtZbbOrZbp, IsRV64] in { def : InstAlias<"rorw $rd, $rs1, $shamt", (RORIW GPR:$rd, GPR:$rs1, uimm5:$shamt), 0>; } // Predicates = [HasStdExtZbbOrZbp, IsRV64] let Predicates = [HasStdExtZbp] in { def : InstAlias<"grev $rd, $rs1, $shamt", (GREVI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>; def : InstAlias<"gorc $rd, $rs1, $shamt", (GORCI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>; def : InstAlias<"shfl $rd, $rs1, $shamt", (SHFLI GPR:$rd, GPR:$rs1, shfl_uimm:$shamt), 0>; def : InstAlias<"unshfl $rd, $rs1, $shamt", (UNSHFLI GPR:$rd, GPR:$rs1, shfl_uimm:$shamt), 0>; } // Predicates = [HasStdExtZbp] let Predicates = [HasStdExtZbp, IsRV64] in { def : InstAlias<"grevw $rd, $rs1, $shamt", (GREVIW GPR:$rd, GPR:$rs1, uimm5:$shamt), 0>; def : InstAlias<"gorcw $rd, $rs1, $shamt", (GORCIW GPR:$rd, GPR:$rs1, uimm5:$shamt), 0>; } // Predicates = [HasStdExtZbp, IsRV64] // Zbp is unratified and that it would likely adopt the already ratified Zbkx names. // Thus current Zbp instructions are defined as aliases for Zbkx instructions. let Predicates = [HasStdExtZbp] in { def : InstAlias<"xperm.b $rd, $rs1, $rs2", (XPERM8 GPR:$rd, GPR:$rs1, GPR:$rs2)>; def : InstAlias<"xperm.n $rd, $rs1, $rs2", (XPERM4 GPR:$rd, GPR:$rs1, GPR:$rs2)>; } // Predicates = [HasStdExtZbp] let Predicates = [HasStdExtZbs] in { def : InstAlias<"bset $rd, $rs1, $shamt", (BSETI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>; def : InstAlias<"bclr $rd, $rs1, $shamt", (BCLRI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>; def : InstAlias<"binv $rd, $rs1, $shamt", (BINVI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>; def : InstAlias<"bext $rd, $rs1, $shamt", (BEXTI GPR:$rd, GPR:$rs1, uimmlog2xlen:$shamt), 0>; } // Predicates = [HasStdExtZbs] //===----------------------------------------------------------------------===// // Codegen patterns //===----------------------------------------------------------------------===// let Predicates = [HasStdExtZbbOrZbpOrZbkb] in { def : Pat<(and GPR:$rs1, (not GPR:$rs2)), (ANDN GPR:$rs1, GPR:$rs2)>; def : Pat<(or GPR:$rs1, (not GPR:$rs2)), (ORN GPR:$rs1, GPR:$rs2)>; def : Pat<(xor GPR:$rs1, (not GPR:$rs2)), (XNOR GPR:$rs1, GPR:$rs2)>; } // Predicates = [HasStdExtZbbOrZbpOrZbkb] let Predicates = [HasStdExtZbbOrZbpOrZbkb] in { def : PatGprGpr<shiftop<rotl>, ROL>; def : PatGprGpr<shiftop<rotr>, ROR>; def : PatGprImm<rotr, RORI, uimmlog2xlen>; // There's no encoding for roli in the the 'B' extension as it can be // implemented with rori by negating the immediate. def : Pat<(rotl GPR:$rs1, uimmlog2xlen:$shamt), (RORI GPR:$rs1, (ImmSubFromXLen uimmlog2xlen:$shamt))>; } // Predicates = [HasStdExtZbbOrZbpOrZbkb] let Predicates = [HasStdExtZbbOrZbpOrZbkb, IsRV64] in { def : PatGprGpr<shiftopw<riscv_rolw>, ROLW>; def : PatGprGpr<shiftopw<riscv_rorw>, RORW>; def : PatGprImm<riscv_rorw, RORIW, uimm5>; def : Pat<(riscv_rolw GPR:$rs1, uimm5:$rs2), (RORIW GPR:$rs1, (ImmSubFrom32 uimm5:$rs2))>; } // Predicates = [HasStdExtZbbOrZbpOrZbkb, IsRV64] let Predicates = [HasStdExtZbs] in { def : Pat<(and (not (shiftop<shl> 1, GPR:$rs2)), GPR:$rs1), (BCLR GPR:$rs1, GPR:$rs2)>; def : Pat<(and (rotl -2, GPR:$rs2), GPR:$rs1), (BCLR GPR:$rs1, GPR:$rs2)>; def : Pat<(or (shiftop<shl> 1, GPR:$rs2), GPR:$rs1), (BSET GPR:$rs1, GPR:$rs2)>; def : Pat<(xor (shiftop<shl> 1, GPR:$rs2), GPR:$rs1), (BINV GPR:$rs1, GPR:$rs2)>; def : Pat<(and (shiftop<srl> GPR:$rs1, GPR:$rs2), 1), (BEXT GPR:$rs1, GPR:$rs2)>; def : Pat<(shiftop<shl> 1, GPR:$rs2), (BSET X0, GPR:$rs2)>; def : Pat<(and GPR:$rs1, BCLRMask:$mask), (BCLRI GPR:$rs1, BCLRMask:$mask)>; def : Pat<(or GPR:$rs1, BSETINVMask:$mask), (BSETI GPR:$rs1, BSETINVMask:$mask)>; def : Pat<(xor GPR:$rs1, BSETINVMask:$mask), (BINVI GPR:$rs1, BSETINVMask:$mask)>; def : Pat<(and (srl GPR:$rs1, uimmlog2xlen:$shamt), (XLenVT 1)), (BEXTI GPR:$rs1, uimmlog2xlen:$shamt)>; def : Pat<(and (not (srl GPR:$rs1, uimmlog2xlen:$shamt)), (XLenVT 1)), (XORI (BEXTI GPR:$rs1, uimmlog2xlen:$shamt), (XLenVT 1))>; def : Pat<(or GPR:$r, BSETINVTwoBitsMask:$i), (BSETI (BSETI GPR:$r, (TrailingZerosXForm BSETINVTwoBitsMask:$i)), (BSETINVTwoBitsMaskHigh BSETINVTwoBitsMask:$i))>; def : Pat<(xor GPR:$r, BSETINVTwoBitsMask:$i), (BINVI (BINVI GPR:$r, (TrailingZerosXForm BSETINVTwoBitsMask:$i)), (BSETINVTwoBitsMaskHigh BSETINVTwoBitsMask:$i))>; def : Pat<(or GPR:$r, BSETINVORIMask:$i), (BSETI (ORI GPR:$r, (BSETINVORIMaskLow BSETINVORIMask:$i)), (BSETINVTwoBitsMaskHigh BSETINVORIMask:$i))>; def : Pat<(xor GPR:$r, BSETINVORIMask:$i), (BINVI (XORI GPR:$r, (BSETINVORIMaskLow BSETINVORIMask:$i)), (BSETINVTwoBitsMaskHigh BSETINVORIMask:$i))>; def : Pat<(and GPR:$r, BCLRITwoBitsMask:$i), (BCLRI (BCLRI GPR:$r, (BCLRITwoBitsMaskLow BCLRITwoBitsMask:$i)), (BCLRITwoBitsMaskHigh BCLRITwoBitsMask:$i))>; def : Pat<(and GPR:$r, BCLRIANDIMask:$i), (BCLRI (ANDI GPR:$r, (BCLRIANDIMaskLow BCLRIANDIMask:$i)), (BCLRITwoBitsMaskHigh BCLRIANDIMask:$i))>; } // Predicates = [HasStdExtZbs] let Predicates = [HasStdExtZbbOrZbp] in { // We treat orc.b as a separate instruction, so match it directly. We also // lower the Zbb orc.b intrinsic to this. def : Pat<(riscv_gorc GPR:$rs1, 7), (ORC_B GPR:$rs1)>; } // Predicates = [HasStdExtZbbOrZbp] let Predicates = [HasStdExtZbpOrZbkb] in { // We treat brev8 as a separate instruction, so match it directly. We also // use this for brev8 when lowering bitreverse with Zbkb. def : Pat<(riscv_grev GPR:$rs1, 7), (BREV8 GPR:$rs1)>; } // Predicates = [HasStdExtZbpOrZbkb] let Predicates = [HasStdExtZbpOrZbkb, IsRV32] in { // We treat zip and unzip as separate instructions, so match it directly. def : Pat<(i32 (riscv_shfl GPR:$rs1, 15)), (ZIP_RV32 GPR:$rs1)>; def : Pat<(i32 (riscv_unshfl GPR:$rs1, 15)), (UNZIP_RV32 GPR:$rs1)>; } // Predicates = [HasStdExtZbpOrZbkb, IsRV32] let Predicates = [HasStdExtZbp] in { def : PatGprGpr<riscv_grev, GREV>; def : PatGprGpr<riscv_gorc, GORC>; def : PatGprImm<riscv_grev, GREVI, uimmlog2xlen>; def : PatGprImm<riscv_gorc, GORCI, uimmlog2xlen>; def : PatGprGpr<riscv_shfl, SHFL>; def : PatGprGpr<riscv_unshfl, UNSHFL>; def : PatGprImm<riscv_shfl, SHFLI, shfl_uimm>; def : PatGprImm<riscv_unshfl, UNSHFLI, shfl_uimm>; def : PatGprGpr<int_riscv_xperm_n, XPERM4>; def : PatGprGpr<int_riscv_xperm_b, XPERM8>; def : PatGprGpr<int_riscv_xperm_h, XPERM_H>; } // Predicates = [HasStdExtZbp] let Predicates = [HasStdExtZbp, IsRV64] in { def : PatGprGpr<riscv_grevw, GREVW>; def : PatGprGpr<riscv_gorcw, GORCW>; // Select GREVIW/GORCIW when the immediate doesn't have bit 5 set and the result // is sign extended. // FIXME: Two special patterns keeped when Imm is 7. def : Pat<(i64 (sext_inreg (binop_oneuse<riscv_grev> GPR:$rs1, 7), i32)), (GREVIW GPR:$rs1, 7)>; def : Pat<(i64 (sext_inreg (binop_oneuse<riscv_gorc> GPR:$rs1, 7), i32)), (GORCIW GPR:$rs1, 7)>; def : PatGprImm<binop_allwusers<riscv_grev>, GREVIW, uimm5>; def : PatGprImm<binop_allwusers<riscv_gorc>, GORCIW, uimm5>; def : PatGprGpr<riscv_shflw, SHFLW>; def : PatGprGpr<riscv_unshflw, UNSHFLW>; } // Predicates = [HasStdExtZbp, IsRV64] let Predicates = [HasStdExtZbp, IsRV64] in def : PatGprGpr<int_riscv_xperm_w, XPERM_W>; let Predicates = [HasStdExtZbp, IsRV32] in { // We treat rev8 as a separate instruction, so match it directly. def : Pat<(i32 (riscv_grev GPR:$rs1, 24)), (REV8_RV32 GPR:$rs1)>; } // Predicates = [HasStdExtZbp, IsRV32] let Predicates = [HasStdExtZbp, IsRV64] in { // We treat rev8 as a separate instruction, so match it directly. def : Pat<(i64 (riscv_grev GPR:$rs1, 56)), (REV8_RV64 GPR:$rs1)>; } // Predicates = [HasStdExtZbp, IsRV64] let Predicates = [HasStdExtZbt] in { def : Pat<(or (and (not GPR:$rs2), GPR:$rs3), (and GPR:$rs2, GPR:$rs1)), (CMIX GPR:$rs1, GPR:$rs2, GPR:$rs3)>; def : Pat<(xor (and (xor GPR:$rs1, GPR:$rs3), GPR:$rs2), GPR:$rs3), (CMIX GPR:$rs1, GPR:$rs2, GPR:$rs3)>; def : Pat<(select (XLenVT (setne GPR:$rs2, 0)), GPR:$rs1, GPR:$rs3), (CMOV GPR:$rs1, GPR:$rs2, GPR:$rs3)>; def : Pat<(select (XLenVT (seteq GPR:$rs2, 0)), GPR:$rs3, GPR:$rs1), (CMOV GPR:$rs1, GPR:$rs2, GPR:$rs3)>; def : Pat<(select (XLenVT (setne GPR:$x, simm12_plus1:$y)), GPR:$rs1, GPR:$rs3), (CMOV GPR:$rs1, (ADDI GPR:$x, (NegImm simm12_plus1:$y)), GPR:$rs3)>; def : Pat<(select (XLenVT (seteq GPR:$x, simm12_plus1:$y)), GPR:$rs3, GPR:$rs1), (CMOV GPR:$rs1, (ADDI GPR:$x, (NegImm simm12_plus1:$y)), GPR:$rs3)>; def : Pat<(select (XLenVT (setne GPR:$x, GPR:$y)), GPR:$rs1, GPR:$rs3), (CMOV GPR:$rs1, (XOR GPR:$x, GPR:$y), GPR:$rs3)>; def : Pat<(select (XLenVT (seteq GPR:$x, GPR:$y)), GPR:$rs3, GPR:$rs1), (CMOV GPR:$rs1, (XOR GPR:$x, GPR:$y), GPR:$rs3)>; def : Pat<(select (XLenVT (setuge GPR:$x, GPR:$y)), GPR:$rs3, GPR:$rs1), (CMOV GPR:$rs1, (SLTU GPR:$x, GPR:$y), GPR:$rs3)>; def : Pat<(select (XLenVT (setule GPR:$y, GPR:$x)), GPR:$rs3, GPR:$rs1), (CMOV GPR:$rs1, (SLTU GPR:$x, GPR:$y), GPR:$rs3)>; def : Pat<(select (XLenVT (setge GPR:$x, GPR:$y)), GPR:$rs3, GPR:$rs1), (CMOV GPR:$rs1, (SLT GPR:$x, GPR:$y), GPR:$rs3)>; def : Pat<(select (XLenVT (setle GPR:$y, GPR:$x)), GPR:$rs3, GPR:$rs1), (CMOV GPR:$rs1, (SLT GPR:$x, GPR:$y), GPR:$rs3)>; // setge X, Imm is canonicalized to setgt X, (Imm - 1). def : Pat<(select (XLenVT (setgt GPR:$x, simm12_minus1_nonzero:$imm)), GPR:$rs3, GPR:$rs1), (CMOV GPR:$rs1, (SLTI GPR:$x, (ImmPlus1 simm12_minus1_nonzero:$imm)), GPR:$rs3)>; def : Pat<(select (XLenVT (setugt GPR:$x, simm12_minus1_nonzero:$imm)), GPR:$rs3, GPR:$rs1), (CMOV GPR:$rs1, (SLTIU GPR:$x, (ImmPlus1 simm12_minus1_nonzero:$imm)), GPR:$rs3)>; def : Pat<(select GPR:$rs2, GPR:$rs1, GPR:$rs3), (CMOV GPR:$rs1, GPR:$rs2, GPR:$rs3)>; } // Predicates = [HasStdExtZbt] let Predicates = [HasStdExtZbt] in { def : Pat<(riscv_fsl GPR:$rs1, GPR:$rs3, GPR:$rs2), (FSL GPR:$rs1, GPR:$rs2, GPR:$rs3)>; def : Pat<(riscv_fsr GPR:$rs1, GPR:$rs3, GPR:$rs2), (FSR GPR:$rs1, GPR:$rs2, GPR:$rs3)>; def : Pat<(riscv_fsr GPR:$rs1, GPR:$rs3, uimmlog2xlen:$shamt), (FSRI GPR:$rs1, GPR:$rs3, uimmlog2xlen:$shamt)>; // We can use FSRI for FSL by immediate if we subtract the immediate from // XLen and swap the operands. def : Pat<(riscv_fsl GPR:$rs3, GPR:$rs1, uimmlog2xlen:$shamt), (FSRI GPR:$rs1, GPR:$rs3, (ImmSubFromXLen uimmlog2xlen:$shamt))>; } // Predicates = [HasStdExtZbt] let Predicates = [HasStdExtZbt, IsRV64] in { def : Pat<(riscv_fslw GPR:$rs1, GPR:$rs3, GPR:$rs2), (FSLW GPR:$rs1, GPR:$rs2, GPR:$rs3)>; def : Pat<(riscv_fsrw GPR:$rs1, GPR:$rs3, GPR:$rs2), (FSRW GPR:$rs1, GPR:$rs2, GPR:$rs3)>; def : Pat<(riscv_fsrw GPR:$rs1, GPR:$rs3, uimm5:$shamt), (FSRIW GPR:$rs1, GPR:$rs3, uimm5:$shamt)>; // We can use FSRIW for FSLW by immediate if we subtract the immediate from // 32 and swap the operands. def : Pat<(riscv_fslw GPR:$rs3, GPR:$rs1, uimm5:$shamt), (FSRIW GPR:$rs1, GPR:$rs3, (ImmSubFrom32 uimm5:$shamt))>; } // Predicates = [HasStdExtZbt, IsRV64] let Predicates = [HasStdExtZbb] in { def : PatGpr<ctlz, CLZ>; def : PatGpr<cttz, CTZ>; def : PatGpr<ctpop, CPOP>; } // Predicates = [HasStdExtZbb] let Predicates = [HasStdExtZbb, IsRV64] in { def : PatGpr<riscv_clzw, CLZW>; def : PatGpr<riscv_ctzw, CTZW>; def : Pat<(i64 (ctpop (i64 (zexti32 (i64 GPR:$rs1))))), (CPOPW GPR:$rs1)>; } // Predicates = [HasStdExtZbb, IsRV64] let Predicates = [HasStdExtZbb] in { def : Pat<(sext_inreg GPR:$rs1, i8), (SEXT_B GPR:$rs1)>; def : Pat<(sext_inreg GPR:$rs1, i16), (SEXT_H GPR:$rs1)>; } // Predicates = [HasStdExtZbb] let Predicates = [HasStdExtZbb] in { def : PatGprGpr<smin, MIN>; def : PatGprGpr<smax, MAX>; def : PatGprGpr<umin, MINU>; def : PatGprGpr<umax, MAXU>; } // Predicates = [HasStdExtZbb] let Predicates = [HasStdExtZbbOrZbkb, IsRV32] in { def : Pat<(i32 (bswap GPR:$rs1)), (REV8_RV32 GPR:$rs1)>; } // Predicates = [HasStdExtZbbOrZbkb, IsRV32] let Predicates = [HasStdExtZbbOrZbkb, IsRV64] in { def : Pat<(i64 (bswap GPR:$rs1)), (REV8_RV64 GPR:$rs1)>; } // Predicates = [HasStdExtZbbOrZbkb, IsRV64] let Predicates = [HasStdExtZbpOrZbkb] in { def : Pat<(or (and (shl GPR:$rs2, (XLenVT 8)), 0xFFFF), (and GPR:$rs1, 0x00FF)), (PACKH GPR:$rs1, GPR:$rs2)>; def : Pat<(or (shl (and GPR:$rs2, 0x00FF), (XLenVT 8)), (and GPR:$rs1, 0x00FF)), (PACKH GPR:$rs1, GPR:$rs2)>; } // Predicates = [HasStdExtZbpOrZbkb] let Predicates = [HasStdExtZbpOrZbkb, IsRV32] in def : Pat<(i32 (or (and GPR:$rs1, 0x0000FFFF), (shl GPR:$rs2, (i32 16)))), (PACK GPR:$rs1, GPR:$rs2)>; let Predicates = [HasStdExtZbpOrZbkb, IsRV64] in { def : Pat<(i64 (or (and GPR:$rs1, 0x00000000FFFFFFFF), (shl GPR:$rs2, (i64 32)))), (PACK GPR:$rs1, GPR:$rs2)>; def : Pat<(i64 (sext_inreg (or (shl GPR:$rs2, (i64 16)), (and GPR:$rs1, 0x000000000000FFFF)), i32)), (PACKW GPR:$rs1, GPR:$rs2)>; def : Pat<(i64 (or (sext_inreg (shl GPR:$rs2, (i64 16)), i32), (and GPR:$rs1, 0x000000000000FFFF))), (PACKW GPR:$rs1, GPR:$rs2)>; } // Predicates = [HasStdExtZbpOrZbkb, IsRV64] let Predicates = [HasStdExtZbp, IsRV32] in def : Pat<(i32 (or (and GPR:$rs2, 0xFFFF0000), (srl GPR:$rs1, (i32 16)))), (PACKU GPR:$rs1, GPR:$rs2)>; let Predicates = [HasStdExtZbp, IsRV64] in { def : Pat<(i64 (or (and GPR:$rs2, 0xFFFFFFFF00000000), (srl GPR:$rs1, (i64 32)))), (PACKU GPR:$rs1, GPR:$rs2)>; def : Pat<(i64 (or (and (assertsexti32 GPR:$rs2), 0xFFFFFFFFFFFF0000), (srl (and GPR:$rs1, 0xFFFFFFFF), (i64 16)))), (PACKUW GPR:$rs1, GPR:$rs2)>; } // Predicates = [HasStdExtZbp, IsRV64] let Predicates = [HasStdExtZbbOrZbp, IsRV32] in def : Pat<(i32 (and GPR:$rs, 0xFFFF)), (ZEXT_H_RV32 GPR:$rs)>; let Predicates = [HasStdExtZbbOrZbp, IsRV64] in def : Pat<(i64 (and GPR:$rs, 0xFFFF)), (ZEXT_H_RV64 GPR:$rs)>; let Predicates = [HasStdExtZba] in { def : Pat<(add (shl GPR:$rs1, (XLenVT 1)), non_imm12:$rs2), (SH1ADD GPR:$rs1, GPR:$rs2)>; def : Pat<(add (shl GPR:$rs1, (XLenVT 2)), non_imm12:$rs2), (SH2ADD GPR:$rs1, GPR:$rs2)>; def : Pat<(add (shl GPR:$rs1, (XLenVT 3)), non_imm12:$rs2), (SH3ADD GPR:$rs1, GPR:$rs2)>; // More complex cases use a ComplexPattern. def : Pat<(add sh1add_op:$rs1, non_imm12:$rs2), (SH1ADD sh1add_op:$rs1, GPR:$rs2)>; def : Pat<(add sh2add_op:$rs1, non_imm12:$rs2), (SH2ADD sh2add_op:$rs1, GPR:$rs2)>; def : Pat<(add sh3add_op:$rs1, non_imm12:$rs2), (SH3ADD sh3add_op:$rs1, GPR:$rs2)>; def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 6)), GPR:$rs2), (SH1ADD (SH1ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 10)), GPR:$rs2), (SH1ADD (SH2ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 18)), GPR:$rs2), (SH1ADD (SH3ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 12)), GPR:$rs2), (SH2ADD (SH1ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 20)), GPR:$rs2), (SH2ADD (SH2ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 36)), GPR:$rs2), (SH2ADD (SH3ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 24)), GPR:$rs2), (SH3ADD (SH1ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 40)), GPR:$rs2), (SH3ADD (SH2ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; def : Pat<(add (mul_oneuse GPR:$rs1, (XLenVT 72)), GPR:$rs2), (SH3ADD (SH3ADD GPR:$rs1, GPR:$rs1), GPR:$rs2)>; def : Pat<(add GPR:$r, CSImm12MulBy4:$i), (SH2ADD (ADDI X0, (SimmShiftRightBy2XForm CSImm12MulBy4:$i)), GPR:$r)>; def : Pat<(add GPR:$r, CSImm12MulBy8:$i), (SH3ADD (ADDI X0, (SimmShiftRightBy3XForm CSImm12MulBy8:$i)), GPR:$r)>; def : Pat<(mul GPR:$r, C3LeftShift:$i), (SLLI (SH1ADD GPR:$r, GPR:$r), (TrailingZerosXForm C3LeftShift:$i))>; def : Pat<(mul GPR:$r, C5LeftShift:$i), (SLLI (SH2ADD GPR:$r, GPR:$r), (TrailingZerosXForm C5LeftShift:$i))>; def : Pat<(mul GPR:$r, C9LeftShift:$i), (SLLI (SH3ADD GPR:$r, GPR:$r), (TrailingZerosXForm C9LeftShift:$i))>; def : Pat<(mul_const_oneuse GPR:$r, (XLenVT 11)), (SH1ADD (SH2ADD GPR:$r, GPR:$r), GPR:$r)>; def : Pat<(mul_const_oneuse GPR:$r, (XLenVT 19)), (SH1ADD (SH3ADD GPR:$r, GPR:$r), GPR:$r)>; def : Pat<(mul_const_oneuse GPR:$r, (XLenVT 13)), (SH2ADD (SH1ADD GPR:$r, GPR:$r), GPR:$r)>; def : Pat<(mul_const_oneuse GPR:$r, (XLenVT 21)), (SH2ADD (SH2ADD GPR:$r, GPR:$r), GPR:$r)>; def : Pat<(mul_const_oneuse GPR:$r, (XLenVT 37)), (SH2ADD (SH3ADD GPR:$r, GPR:$r), GPR:$r)>; def : Pat<(mul_const_oneuse GPR:$r, (XLenVT 25)), (SH3ADD (SH1ADD GPR:$r, GPR:$r), GPR:$r)>; def : Pat<(mul_const_oneuse GPR:$r, (XLenVT 41)), (SH3ADD (SH2ADD GPR:$r, GPR:$r), GPR:$r)>; def : Pat<(mul_const_oneuse GPR:$r, (XLenVT 73)), (SH3ADD (SH3ADD GPR:$r, GPR:$r), GPR:$r)>; def : Pat<(mul_const_oneuse GPR:$r, (XLenVT 27)), (SH1ADD (SH3ADD GPR:$r, GPR:$r), (SH3ADD GPR:$r, GPR:$r))>; def : Pat<(mul_const_oneuse GPR:$r, (XLenVT 45)), (SH2ADD (SH3ADD GPR:$r, GPR:$r), (SH3ADD GPR:$r, GPR:$r))>; def : Pat<(mul_const_oneuse GPR:$r, (XLenVT 81)), (SH3ADD (SH3ADD GPR:$r, GPR:$r), (SH3ADD GPR:$r, GPR:$r))>; } // Predicates = [HasStdExtZba] let Predicates = [HasStdExtZba, IsRV64] in { def : Pat<(i64 (shl (and GPR:$rs1, 0xFFFFFFFF), uimm5:$shamt)), (SLLI_UW GPR:$rs1, uimm5:$shamt)>; def : Pat<(i64 (add (and GPR:$rs1, 0xFFFFFFFF), non_imm12:$rs2)), (ADD_UW GPR:$rs1, GPR:$rs2)>; def : Pat<(i64 (and GPR:$rs, 0xFFFFFFFF)), (ADD_UW GPR:$rs, X0)>; def : Pat<(i64 (add (shl (and GPR:$rs1, 0xFFFFFFFF), (i64 1)), non_imm12:$rs2)), (SH1ADD_UW GPR:$rs1, GPR:$rs2)>; def : Pat<(i64 (add (shl (and GPR:$rs1, 0xFFFFFFFF), (i64 2)), non_imm12:$rs2)), (SH2ADD_UW GPR:$rs1, GPR:$rs2)>; def : Pat<(i64 (add (shl (and GPR:$rs1, 0xFFFFFFFF), (i64 3)), non_imm12:$rs2)), (SH3ADD_UW GPR:$rs1, GPR:$rs2)>; def : Pat<(i64 (add (and (shl GPR:$rs1, (i64 1)), 0x1FFFFFFFF), non_imm12:$rs2)), (SH1ADD_UW GPR:$rs1, GPR:$rs2)>; def : Pat<(i64 (add (and (shl GPR:$rs1, (i64 2)), 0x3FFFFFFFF), non_imm12:$rs2)), (SH2ADD_UW GPR:$rs1, GPR:$rs2)>; def : Pat<(i64 (add (and (shl GPR:$rs1, (i64 3)), 0x7FFFFFFFF), non_imm12:$rs2)), (SH3ADD_UW GPR:$rs1, GPR:$rs2)>; def : Pat<(i64 (add (and GPR:$rs1, 0xFFFFFFFE), non_imm12:$rs2)), (SH1ADD (SRLIW GPR:$rs1, 1), GPR:$rs2)>; def : Pat<(i64 (add (and GPR:$rs1, 0xFFFFFFFC), non_imm12:$rs2)), (SH2ADD (SRLIW GPR:$rs1, 2), GPR:$rs2)>; def : Pat<(i64 (add (and GPR:$rs1, 0xFFFFFFF8), non_imm12:$rs2)), (SH3ADD (SRLIW GPR:$rs1, 3), GPR:$rs2)>; // Use SRLI to clear the LSBs and SHXADD_UW to mask and shift. def : Pat<(i64 (add (and GPR:$rs1, 0x1FFFFFFFE), non_imm12:$rs2)), (SH1ADD_UW (SRLI GPR:$rs1, 1), GPR:$rs2)>; def : Pat<(i64 (add (and GPR:$rs1, 0x3FFFFFFFC), non_imm12:$rs2)), (SH2ADD_UW (SRLI GPR:$rs1, 2), GPR:$rs2)>; def : Pat<(i64 (add (and GPR:$rs1, 0x7FFFFFFF8), non_imm12:$rs2)), (SH3ADD_UW (SRLI GPR:$rs1, 3), GPR:$rs2)>; } // Predicates = [HasStdExtZba, IsRV64] let Predicates = [HasStdExtZbcOrZbkc] in { def : PatGprGpr<int_riscv_clmul, CLMUL>; def : PatGprGpr<int_riscv_clmulh, CLMULH>; } // Predicates = [HasStdExtZbcOrZbkc] let Predicates = [HasStdExtZbc] in def : PatGprGpr<int_riscv_clmulr, CLMULR>; let Predicates = [HasStdExtZbe] in { def : PatGprGpr<riscv_bcompress, BCOMPRESS>; def : PatGprGpr<riscv_bdecompress, BDECOMPRESS>; } // Predicates = [HasStdExtZbe] let Predicates = [HasStdExtZbe, IsRV64] in { def : PatGprGpr<riscv_bcompressw, BCOMPRESSW>; def : PatGprGpr<riscv_bdecompressw, BDECOMPRESSW>; } // Predicates = [HasStdExtZbe, IsRV64] let Predicates = [HasStdExtZbr] in { def : PatGpr<int_riscv_crc32_b, CRC32_B>; def : PatGpr<int_riscv_crc32_h, CRC32_H>; def : PatGpr<int_riscv_crc32_w, CRC32_W>; def : PatGpr<int_riscv_crc32c_b, CRC32C_B>; def : PatGpr<int_riscv_crc32c_h, CRC32C_H>; def : PatGpr<int_riscv_crc32c_w, CRC32C_W>; } // Predicates = [HasStdExtZbr] let Predicates = [HasStdExtZbr, IsRV64] in { def : PatGpr<int_riscv_crc32_d, CRC32_D>; def : PatGpr<int_riscv_crc32c_d, CRC32C_D>; } // Predicates = [HasStdExtZbr, IsRV64] let Predicates = [HasStdExtZbf] in def : PatGprGpr<riscv_bfp, BFP>; let Predicates = [HasStdExtZbf, IsRV64] in def : PatGprGpr<riscv_bfpw, BFPW>; let Predicates = [HasStdExtZbkx] in { def : PatGprGpr<int_riscv_xperm4, XPERM4>; def : PatGprGpr<int_riscv_xperm8, XPERM8>; } // Predicates = [HasStdExtZbkx]