aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td')
-rw-r--r--contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td264
1 files changed, 167 insertions, 97 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td b/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
index 07884d35f63c..9532d1dd3dd2 100644
--- a/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
+++ b/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
@@ -211,15 +211,16 @@ def CSImm12MulBy4 : PatLeaf<(imm), [{
return false;
int64_t C = N->getSExtValue();
// Skip if C is simm12 or can be optimized by the PatLeaf AddiPair.
- return !isInt<13>(C) && isInt<14>(C) && (C & 3) == 0;
+ 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.
- return !isInt<13>(C) && isInt<15>(C) && (C & 7) == 0;
+ // 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, [{
@@ -232,6 +233,12 @@ def SimmShiftRightBy3XForm : SDNodeXForm<imm, [{
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());
+}]>;
+
//===----------------------------------------------------------------------===//
// Instruction class templates
//===----------------------------------------------------------------------===//
@@ -348,7 +355,7 @@ 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 = [HasStdExtZbb, IsRV64]
+} // Predicates = [HasStdExtZba, IsRV64]
let Predicates = [HasStdExtZbbOrZbpOrZbkb] in {
def ROL : ALU_rr<0b0110000, 0b001, "rol">,
@@ -368,7 +375,7 @@ def RORW : ALUW_rr<0b0110000, 0b101, "rorw">,
def RORIW : RVBShiftW_ri<0b0110000, 0b101, OPC_OP_IMM_32, "roriw">,
Sched<[WriteRotateImm32, ReadRotateImm32]>;
-} // Predicates = [HasStdExtZbbOrZbp, IsRV64]
+} // Predicates = [HasStdExtZbbOrZbpOrZbkb, IsRV64]
let Predicates = [HasStdExtZbs] in {
def BCLR : ALU_rr<0b0100100, 0b001, "bclr">,
@@ -391,32 +398,48 @@ def BEXTI : RVBShift_ri<0b01001, 0b101, OPC_OP_IMM, "bexti">,
} // Predicates = [HasStdExtZbs]
let Predicates = [HasStdExtZbp] in {
-def GORC : ALU_rr<0b0010100, 0b101, "gorc">, Sched<[]>;
-def GREV : ALU_rr<0b0110100, 0b101, "grev">, Sched<[]>;
-
-def GREVI : RVBShift_ri<0b01101, 0b101, OPC_OP_IMM, "grevi">, Sched<[]>;
-def GORCI : RVBShift_ri<0b00101, 0b101, OPC_OP_IMM, "gorci">, Sched<[]>;
-
-def SHFL : ALU_rr<0b0000100, 0b001, "shfl">, Sched<[]>;
-def UNSHFL : ALU_rr<0b0000100, 0b101, "unshfl">, Sched<[]>;
-
-def SHFLI : RVBShfl_ri<0b0000100, 0b001, OPC_OP_IMM, "shfli">, Sched<[]>;
-def UNSHFLI : RVBShfl_ri<0b0000100, 0b101, OPC_OP_IMM, "unshfli">, Sched<[]>;
-
-def XPERM_H : ALU_rr<0b0010100, 0b110, "xperm.h">, Sched<[]>;
+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<[]>;
-def GREVW : ALUW_rr<0b0110100, 0b101, "grevw">, Sched<[]>;
-
-def GORCIW : RVBShiftW_ri<0b0010100, 0b101, OPC_OP_IMM_32, "gorciw">, Sched<[]>;
-def GREVIW : RVBShiftW_ri<0b0110100, 0b101, OPC_OP_IMM_32, "greviw">, Sched<[]>;
-
-def SHFLW : ALUW_rr<0b0000100, 0b001, "shflw">, Sched<[]>;
-def UNSHFLW : ALUW_rr<0b0000100, 0b101, "unshflw">, Sched<[]>;
-
-def XPERM_W : ALU_rr<0b0010100, 0b000, "xperm.w">, Sched<[]>;
+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
@@ -429,24 +452,28 @@ def XPERM8 : ALU_rr<0b0010100, 0b100, "xperm8">, Sched<[]>;
let Predicates = [HasStdExtZbt] in {
def CMIX : RVBTernaryR<0b11, 0b001, OPC_OP, "cmix", "$rd, $rs2, $rs1, $rs3">,
- Sched<[]>;
+ Sched<[WriteCMix, ReadCMix, ReadCMix, ReadCMix]>;
def CMOV : RVBTernaryR<0b11, 0b101, OPC_OP, "cmov", "$rd, $rs2, $rs1, $rs3">,
- Sched<[]>;
+ Sched<[WriteCMov, ReadCMov, ReadCMov, ReadCMov]>;
def FSL : RVBTernaryR<0b10, 0b001, OPC_OP, "fsl", "$rd, $rs1, $rs3, $rs2">,
- Sched<[]>;
+ Sched<[WriteFSReg, ReadFSReg, ReadFSReg, ReadFSReg]>;
def FSR : RVBTernaryR<0b10, 0b101, OPC_OP, "fsr", "$rd, $rs1, $rs3, $rs2">,
- Sched<[]>;
+ Sched<[WriteFSReg, ReadFSReg, ReadFSReg, ReadFSReg]>;
def FSRI : RVBTernaryImm6<0b101, OPC_OP_IMM, "fsri",
- "$rd, $rs1, $rs3, $shamt">, Sched<[]>;
+ "$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<[]>;
+ "fslw", "$rd, $rs1, $rs3, $rs2">,
+ Sched<[WriteFSReg32, ReadFSReg32, ReadFSReg32, ReadFSReg32]>;
def FSRW : RVBTernaryR<0b10, 0b101, OPC_OP_32, "fsrw",
- "$rd, $rs1, $rs3, $rs2">, Sched<[]>;
+ "$rd, $rs1, $rs3, $rs2">,
+ Sched<[WriteFSReg32, ReadFSReg32, ReadFSReg32, ReadFSReg32]>;
def FSRIW : RVBTernaryImm5<0b10, 0b101, OPC_OP_IMM_32,
- "fsriw", "$rd, $rs1, $rs3, $shamt">, Sched<[]>;
+ "fsriw", "$rd, $rs1, $rs3, $shamt">,
+ Sched<[WriteFSRImm32, ReadFSRImm32, ReadFSRImm32]>;
} // Predicates = [HasStdExtZbt, IsRV64]
let Predicates = [HasStdExtZbb] in {
@@ -476,88 +503,96 @@ def SEXT_H : RVBUnary<0b0110000, 0b00101, 0b001, OPC_OP_IMM, "sext.h">,
let Predicates = [HasStdExtZbr] in {
def CRC32_B : RVBUnary<0b0110000, 0b10000, 0b001, OPC_OP_IMM, "crc32.b">,
- Sched<[]>;
+ Sched<[WriteCRCB, ReadCRCB]>;
def CRC32_H : RVBUnary<0b0110000, 0b10001, 0b001, OPC_OP_IMM, "crc32.h">,
- Sched<[]>;
+ Sched<[WriteCRCH, ReadCRCH]>;
def CRC32_W : RVBUnary<0b0110000, 0b10010, 0b001, OPC_OP_IMM, "crc32.w">,
- Sched<[]>;
+ Sched<[WriteCRCW, ReadCRCW]>;
def CRC32C_B : RVBUnary<0b0110000, 0b11000, 0b001, OPC_OP_IMM, "crc32c.b">,
- Sched<[]>;
+ Sched<[WriteCRCCB, ReadCRCCB]>;
def CRC32C_H : RVBUnary<0b0110000, 0b11001, 0b001, OPC_OP_IMM, "crc32c.h">,
- Sched<[]>;
+ Sched<[WriteCRCCH, ReadCRCCH]>;
def CRC32C_W : RVBUnary<0b0110000, 0b11010, 0b001, OPC_OP_IMM, "crc32c.w">,
- Sched<[]>;
+ Sched<[WriteCRCCW, ReadCRCCW]>;
} // Predicates = [HasStdExtZbr]
let Predicates = [HasStdExtZbr, IsRV64] in {
def CRC32_D : RVBUnary<0b0110000, 0b10011, 0b001, OPC_OP_IMM, "crc32.d">,
- Sched<[]>;
+ Sched<[WriteCRCD, ReadCRCD]>;
def CRC32C_D : RVBUnary<0b0110000, 0b11011, 0b001, OPC_OP_IMM, "crc32c.d">,
- Sched<[]>;
+ Sched<[WriteCRCCD, ReadCRCCD]>;
} // Predicates = [HasStdExtZbr, IsRV64]
let Predicates = [HasStdExtZbc] in {
-def CLMULR : ALU_rr<0b0000101, 0b010, "clmulr">,
+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">,
+def CLMUL : ALU_rr<0b0000101, 0b001, "clmul", /*Commutable*/1>,
Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>;
-def CLMULH : ALU_rr<0b0000101, 0b011, "clmulh">,
+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">,
+def MIN : ALU_rr<0b0000101, 0b100, "min", /*Commutable*/1>,
Sched<[WriteIALU, ReadIALU, ReadIALU]>;
-def MINU : ALU_rr<0b0000101, 0b101, "minu">,
+def MINU : ALU_rr<0b0000101, 0b101, "minu", /*Commutable*/1>,
Sched<[WriteIALU, ReadIALU, ReadIALU]>;
-def MAX : ALU_rr<0b0000101, 0b110, "max">,
+def MAX : ALU_rr<0b0000101, 0b110, "max", /*Commutable*/1>,
Sched<[WriteIALU, ReadIALU, ReadIALU]>;
-def MAXU : ALU_rr<0b0000101, 0b111, "maxu">,
+def MAXU : ALU_rr<0b0000101, 0b111, "maxu", /*Commutable*/1>,
Sched<[WriteIALU, ReadIALU, ReadIALU]>;
} // Predicates = [HasStdExtZbb]
-let Predicates = [HasStdExtZbp] in {
-} // Predicates = [HasStdExtZbp]
-
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<[]>;
-def BCOMPRESS : ALU_rr<0b0000100, 0b110, "bcompress">, Sched<[]>;
+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<[]>;
-def BCOMPRESSW : ALUW_rr<0b0000100, 0b110, "bcompressw">, Sched<[]>;
+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<[]>;
-def PACKH : ALU_rr<0b0000100, 0b111, "packh">, Sched<[]>;
+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<[]>;
+def PACKW : ALUW_rr<0b0000100, 0b100, "packw">,
+ Sched<[WritePACK32, ReadPACK32, ReadPACK32]>;
let Predicates = [HasStdExtZbp] in
-def PACKU : ALU_rr<0b0100100, 0b100, "packu">, Sched<[]>;
+def PACKU : ALU_rr<0b0100100, 0b100, "packu">,
+ Sched<[WritePACKU, ReadPACKU, ReadPACKU]>;
let Predicates = [HasStdExtZbp, IsRV64] in
-def PACKUW : ALUW_rr<0b0100100, 0b100, "packuw">, Sched<[]>;
+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<[]>;
+ Sched<[WriteBMatrix, ReadBMatrix]>;
-def BMATOR : ALU_rr<0b0000100, 0b011, "bmator">, Sched<[]>;
-def BMATXOR : ALU_rr<0b0100100, 0b011, "bmatxor">, Sched<[]>;
+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
@@ -601,12 +636,15 @@ def ORC_B : RVBUnary<0b0010100, 0b00111, 0b101, OPC_OP_IMM, "orc.b">,
} // Predicates = [HasStdExtZbbOrZbp]
let Predicates = [HasStdExtZbpOrZbkb] in
-def BREV8 : RVBUnary<0b0110100, 0b00111, 0b101, OPC_OP_IMM, "brev8">;
+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">;
-def UNZIP_RV32 : RVBUnary<0b0000100, 0b01111, 0b101, OPC_OP_IMM, "unzip">;
-} // Predicates = [HasStdExtZbkb, IsRV32]
+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]
//===----------------------------------------------------------------------===//
@@ -615,7 +653,7 @@ def UNZIP_RV32 : RVBUnary<0b0000100, 0b01111, 0b101, OPC_OP_IMM, "unzip">;
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)>;
@@ -780,8 +818,8 @@ def : Pat<(xor GPR:$rs1, (not GPR:$rs2)), (XNOR GPR:$rs1, GPR:$rs2)>;
} // Predicates = [HasStdExtZbbOrZbpOrZbkb]
let Predicates = [HasStdExtZbbOrZbpOrZbkb] in {
-def : PatGprGpr<rotl, ROL>;
-def : PatGprGpr<rotr, ROR>;
+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
@@ -791,8 +829,8 @@ def : Pat<(rotl GPR:$rs1, uimmlog2xlen:$shamt),
} // Predicates = [HasStdExtZbbOrZbpOrZbkb]
let Predicates = [HasStdExtZbbOrZbpOrZbkb, IsRV64] in {
-def : PatGprGpr<riscv_rolw, ROLW>;
-def : PatGprGpr<riscv_rorw, RORW>;
+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))>;
@@ -843,23 +881,25 @@ def : Pat<(and GPR:$r, 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>;
@@ -880,12 +920,16 @@ def : PatGprGpr<int_riscv_xperm_h, XPERM_H>;
let Predicates = [HasStdExtZbp, IsRV64] in {
def : PatGprGpr<riscv_grevw, GREVW>;
def : PatGprGpr<riscv_gorcw, GORCW>;
-def : PatGprImm<riscv_grevw, GREVIW, uimm5>;
-def : PatGprImm<riscv_gorcw, GORCIW, uimm5>;
-// FIXME: Move to DAG combine.
-def : Pat<(riscv_rorw (riscv_grevw GPR:$rs1, 24), 16), (GREVIW GPR:$rs1, 8)>;
-def : Pat<(riscv_rolw (riscv_grevw GPR:$rs1, 24), 16), (GREVIW GPR:$rs1, 8)>;
+// 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>;
@@ -895,10 +939,6 @@ let Predicates = [HasStdExtZbp, IsRV64] in
def : PatGprGpr<int_riscv_xperm_w, XPERM_W>;
let Predicates = [HasStdExtZbp, IsRV32] in {
-// FIXME : Move to DAG combine.
-def : Pat<(i32 (rotr (riscv_grev GPR:$rs1, 24), (i32 16))), (GREVI GPR:$rs1, 8)>;
-def : Pat<(i32 (rotl (riscv_grev GPR:$rs1, 24), (i32 16))), (GREVI GPR:$rs1, 8)>;
-
// 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]
@@ -911,6 +951,8 @@ def : Pat<(i64 (riscv_grev GPR:$rs1, 56)), (REV8_RV64 GPR:$rs1)>;
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)>;
@@ -932,6 +974,13 @@ 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]
@@ -977,7 +1026,7 @@ def : Pat<(i64 (ctpop (i64 (zexti32 (i64 GPR:$rs1))))), (CPOPW GPR:$rs1)>;
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>;
@@ -1018,7 +1067,7 @@ def : Pat<(i64 (sext_inreg (or (shl GPR:$rs2, (i64 16)),
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)))),
@@ -1031,19 +1080,13 @@ def : Pat<(i64 (or (and GPR:$rs2, 0xFFFFFFFF00000000), (srl GPR:$rs1, (i64 32)))
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)>;
-// 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());
-}]>;
-
let Predicates = [HasStdExtZba] in {
def : Pat<(add (shl GPR:$rs1, (XLenVT 1)), non_imm12:$rs2),
(SH1ADD GPR:$rs1, GPR:$rs2)>;
@@ -1132,6 +1175,33 @@ 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)>;
+
+// Use SRLIW to shift out the LSBs and zero the upper 32-bits. Use SHXADD to
+// shift zeros into the LSBs the addition shl amount.
+def : Pat<(i64 (add (shl (binop_oneuse<and> GPR:$rs1, 0xFFFFFFFE), (i64 1)),
+ non_imm12:$rs2)),
+ (SH2ADD (SRLIW GPR:$rs1, 1), GPR:$rs2)>;
+def : Pat<(i64 (add (shl (binop_oneuse<and> GPR:$rs1, 0xFFFFFFFE), (i64 2)),
+ non_imm12:$rs2)),
+ (SH3ADD (SRLIW GPR:$rs1, 1), GPR:$rs2)>;
+def : Pat<(i64 (add (shl (binop_oneuse<and> GPR:$rs1, 0xFFFFFFFC), (i64 1)),
+ non_imm12:$rs2)),
+ (SH3ADD (SRLIW GPR:$rs1, 2), GPR:$rs2)>;
} // Predicates = [HasStdExtZba, IsRV64]
let Predicates = [HasStdExtZbcOrZbkc] in {
@@ -1175,4 +1245,4 @@ def : PatGprGpr<riscv_bfpw, BFPW>;
let Predicates = [HasStdExtZbkx] in {
def : PatGprGpr<int_riscv_xperm4, XPERM4>;
def : PatGprGpr<int_riscv_xperm8, XPERM8>;
-}
+} // Predicates = [HasStdExtZbkx]