[llvm] [RISCV] Add P-ext MC support for pli.dh, pli.db, and plui.dh. (PR #153972)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 16 11:58:34 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
Author: Craig Topper (topperc)
<details>
<summary>Changes</summary>
Refactor the pli.b/h/w and plui.h/w tablegen classes.
Stacked on #<!-- -->153913
---
Full diff: https://github.com/llvm/llvm-project/pull/153972.diff
7 Files Affected:
- (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+12)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h (+1)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoP.td (+97-33)
- (modified) llvm/test/MC/RISCV/rv32p-invalid.s (+9-1)
- (modified) llvm/test/MC/RISCV/rv32p-valid.s (+19)
- (modified) llvm/test/MC/RISCV/rv64p-invalid.s (+5)
- (modified) llvm/test/MC/RISCV/rv64p-valid.s (+6)
``````````diff
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index d71c42c0a5fc1..d37ae2ffb7e3a 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -903,6 +903,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
VK == RISCV::S_QC_ABS20;
}
+ bool isSImm8Unsigned() const { return isSImm<8>() || isUImm<8>(); }
bool isSImm10Unsigned() const { return isSImm<10>() || isUImm<10>(); }
bool isUImm20LUI() const {
@@ -1199,6 +1200,14 @@ struct RISCVOperand final : public MCParsedAsmOperand {
addExpr(Inst, getImm(), isRV64Imm());
}
+ void addSImm8UnsignedOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ int64_t Imm;
+ [[maybe_unused]] bool IsConstant = evaluateConstantImm(getImm(), Imm);
+ assert(IsConstant);
+ Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));
+ }
+
void addSImm10UnsignedOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
int64_t Imm;
@@ -1547,6 +1556,9 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return generateImmOutOfRangeError(
Operands, ErrorInfo, 0, (1 << 9) - 8,
"immediate must be a multiple of 8 bytes in the range");
+ case Match_InvalidSImm8Unsigned:
+ return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 7),
+ (1 << 8) - 1);
case Match_InvalidSImm10:
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 9),
(1 << 9) - 1);
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 9d26fc01bf379..083ac056ac72c 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -346,6 +346,7 @@ enum OperandType : unsigned {
OPERAND_SIMM5_PLUS1,
OPERAND_SIMM6,
OPERAND_SIMM6_NONZERO,
+ OPERAND_SIMM8,
OPERAND_SIMM10,
OPERAND_SIMM10_LSB0000_NONZERO,
OPERAND_SIMM11,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index e67417035963a..a7d2e7c7b1bbf 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -18,7 +18,26 @@
// Operand and SDNode transformation definitions.
//===----------------------------------------------------------------------===//
-def simm10 : RISCVSImmLeafOp<10>;
+def simm10 : RISCVSImmOp<10>;
+
+def SImm8UnsignedAsmOperand : SImmAsmOperand<8, "Unsigned"> {
+ let RenderMethod = "addSImm8UnsignedOperands";
+}
+
+// A 8-bit signed immediate allowing range [-128, 255]
+// but represented as [-128, 255].
+def simm8_unsigned : RISCVOp {
+ let ParserMatchClass = SImm8UnsignedAsmOperand;
+ let EncoderMethod = "getImmOpValue";
+ let DecoderMethod = "decodeSImmOperand<8>";
+ let OperandType = "OPERAND_SIMM10";
+ let MCOperandPredicate = [{
+ int64_t Imm;
+ if (!MCOp.evaluateAsConstantImm(Imm))
+ return false;
+ return isInt<8>(Imm);
+ }];
+}
def SImm10UnsignedAsmOperand : SImmAsmOperand<10, "Unsigned"> {
let RenderMethod = "addSImm10UnsignedOperands";
@@ -43,49 +62,40 @@ def simm10_unsigned : RISCVOp {
// Instruction class templates
//===----------------------------------------------------------------------===//
-let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
-class PLI_i<bits<7> funct7, string opcodestr>
- : RVInst<(outs GPR:$rd), (ins simm10:$imm10), opcodestr, "$rd, $imm10", [],
+// Common base for pli.b/h/w and plui.h/w
+class RVPLoadImm_i<bits<7> funct7, dag ins, string opcodestr,
+ string argstr>
+ : RVInst<(outs GPR:$rd), ins, opcodestr, argstr, [],
InstFormatOther> {
- bits<10> imm10;
bits<5> rd;
let Inst{31-25} = funct7;
- let Inst{24-16} = imm10{8-0};
- let Inst{15} = imm10{9};
let Inst{14-12} = 0b010;
let Inst{11-7} = rd;
let Inst{6-0} = OPC_OP_IMM_32.Value;
+
+ let hasSideEffects = 0;
+ let mayLoad = 0;
+ let mayStore = 0;
}
-let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
-class PLUI_i<bits<7> funct7, string opcodestr>
- : RVInst<(outs GPR:$rd), (ins simm10_unsigned:$imm10), opcodestr,
- "$rd, $imm10", [], InstFormatOther> {
+// Base for pli.h/w.
+class PLI_i<bits<7> funct7, string opcodestr>
+ : RVPLoadImm_i<funct7, (ins simm10:$imm10), opcodestr, "$rd, $imm10"> {
bits<10> imm10;
- bits<5> rd;
- let Inst{31-25} = funct7;
- let Inst{24} = imm10{0};
- let Inst{23-15} = imm10{9-1};
- let Inst{14-12} = 0b010;
- let Inst{11-7} = rd;
- let Inst{6-0} = OPC_OP_IMM_32.Value;
+ let Inst{24-16} = imm10{8-0};
+ let Inst{15} = imm10{9};
}
-let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
-class PLI_B_i<bits<8> funct8, string opcodestr>
- : RVInst<(outs GPR:$rd), (ins uimm8:$uimm8), opcodestr, "$rd, $uimm8", [],
- InstFormatOther> {
- bits<8> uimm8;
- bits<5> rd;
+// Base for plui.h/w.
+class PLUI_i<bits<7> funct7, string opcodestr>
+ : RVPLoadImm_i<funct7, (ins simm10_unsigned:$imm10), opcodestr,
+ "$rd, $imm10"> {
+ bits<10> imm10;
- let Inst{31-24} = funct8;
- let Inst{23-16} = uimm8;
- let Inst{15} = 0b0;
- let Inst{14-12} = 0b010;
- let Inst{11-7} = rd;
- let Inst{6-0} = OPC_OP_IMM_32.Value;
+ let Inst{24} = imm10{0};
+ let Inst{23-15} = imm10{9-1};
}
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
@@ -161,7 +171,8 @@ class RVPBinary_rr<bits<4> f, bits<2> w, bits<3> funct3, string opcodestr>
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
class RVPTernary_rrr<bits<4> f, bits<2> w, bits<3> funct3, string opcodestr>
: RVInstRBase<funct3, OPC_OP_32, (outs GPR:$rd_wb),
- (ins GPR:$rd, GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2"> {
+ (ins GPR:$rd, GPR:$rs1, GPR:$rs2), opcodestr,
+ "$rd, $rs1, $rs2"> {
let Inst{31} = 0b1;
let Inst{30-27} = f;
let Inst{26-25} = w;
@@ -169,6 +180,24 @@ class RVPTernary_rrr<bits<4> f, bits<2> w, bits<3> funct3, string opcodestr>
let Constraints = "$rd = $rd_wb";
}
+// Common base for pli.b/h/w and plui.h/w
+class RVPPairLoadImm_i<bits<7> funct7, dag ins, string opcodestr,
+ string argstr>
+ : RVInst<(outs GPRPairRV32:$rd), ins, opcodestr, argstr, [],
+ InstFormatOther> {
+ bits<5> rd;
+
+ let Inst{31-25} = funct7;
+ let Inst{14-12} = 0b010;
+ let Inst{11-8} = rd{4-1};
+ let Inst{7} = 0b0;
+ let Inst{6-0} = OPC_OP_IMM_32.Value;
+
+ let hasSideEffects = 0;
+ let mayLoad = 0;
+ let mayStore = 0;
+}
+
//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
@@ -210,8 +239,16 @@ let Predicates = [HasStdExtP] in
def PLI_H : PLI_i<0b1011000, "pli.h">;
let Predicates = [HasStdExtP, IsRV64] in
def PLI_W : PLI_i<0b1011001, "pli.w">;
-let Predicates = [HasStdExtP] in
-def PLI_B : PLI_B_i<0b10110100, "pli.b">;
+let Predicates = [HasStdExtP] in {
+ def PLI_B : RVPLoadImm_i<0b1011010, (ins simm8_unsigned:$imm8), "pli.b",
+ "$rd, $imm8"> {
+ bits<8> imm8;
+
+ let Inst{24} = 0b0;
+ let Inst{23-16} = imm8;
+ let Inst{15} = 0b0;
+ }
+}
let Predicates = [HasStdExtP] in {
def PSEXT_H_B : RVPUnary_ri<0b00, 0b00100, "psext.h.b">;
@@ -559,3 +596,30 @@ let Predicates = [HasStdExtP, IsRV64] in {
def PPACKT_W : RVPBinary_rr<0b0110, 0b01, 0b100, "ppackt.w">;
def PACKT_RV64 : RVPBinary_rr<0b0110, 0b11, 0b100, "packt">;
} // Predicates = [HasStdExtP, IsRV64]
+
+let Predicates = [HasStdExtP, IsRV32] in {
+ def PLI_DH : RVPPairLoadImm_i<0b0011000, (ins simm10:$imm10), "pli.dh",
+ "$rd, $imm10"> {
+ bits<10> imm10;
+
+ let Inst{24-16} = imm10{8-0};
+ let Inst{15} = imm10{9};
+ }
+
+ def PLI_DB : RVPPairLoadImm_i<0b0011010, (ins simm8_unsigned:$imm8), "pli.db",
+ "$rd, $imm8"> {
+ bits<8> imm8;
+
+ let Inst{24} = 0b0;
+ let Inst{23-16} = imm8;
+ let Inst{15} = 0b0;
+ }
+
+ def PLUI_DH : RVPPairLoadImm_i<0b0111000, (ins simm10_unsigned:$imm10),
+ "plui.dh", "$rd, $imm10"> {
+ bits<10> imm10;
+
+ let Inst{24} = imm10{0};
+ let Inst{23-15} = imm10{9-1};
+ }
+}
diff --git a/llvm/test/MC/RISCV/rv32p-invalid.s b/llvm/test/MC/RISCV/rv32p-invalid.s
index 7dd73d077bf3a..b00c39b8811dc 100644
--- a/llvm/test/MC/RISCV/rv32p-invalid.s
+++ b/llvm/test/MC/RISCV/rv32p-invalid.s
@@ -4,7 +4,7 @@
# Imm overflow
pli.h a0, 0x400 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [-512, 511]
plui.h a1, 0x400 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [-512, 1023]
-pli.b a0, 0x200 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [0, 255]
+pli.b a0, 0x200 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [-128, 255]
pslli.b a6, a7, 100 # CHECK: :[[@LINE]]:17: error: immediate must be an integer in the range [0, 7]
pslli.h ra, sp, 100 # CHECK: :[[@LINE]]:17: error: immediate must be an integer in the range [0, 15]
@@ -106,3 +106,11 @@ ppack.w t5, a2, a4 # CHECK: :[[@LINE]]:1: error: instruction requires the follow
ppackbt.w t5, s0, t5 # CHECK: :[[@LINE]]:1: error: instruction requires the following: RV64I Base Instruction Set
ppacktb.w t5, t1, t1 # CHECK: :[[@LINE]]:1: error: instruction requires the following: RV64I Base Instruction Set
ppackt.w t3, a0, s2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: RV64I Base Instruction Set
+
+pli.dh a1, 1 # CHECK: :[[@LINE]]:8: error: register must be even
+pli.db s1, 1 # CHECK: :[[@LINE]]:8: error: register must be even
+plui.dh t2, 1 # CHECK: :[[@LINE]]:9: error: register must be even
+
+pli.dh a0, 0x400 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [-512, 511]
+pli.db a0, 0x200 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [-128, 255]
+plui.dh a0, 0x400 # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [-512, 1023]
diff --git a/llvm/test/MC/RISCV/rv32p-valid.s b/llvm/test/MC/RISCV/rv32p-valid.s
index 0383e4ec1ea62..bc7ec6587c5fc 100644
--- a/llvm/test/MC/RISCV/rv32p-valid.s
+++ b/llvm/test/MC/RISCV/rv32p-valid.s
@@ -61,6 +61,9 @@ pli.h a5, 16
# CHECK-ASM-AND-OBJ: pli.b a6, 16
# CHECK-ASM: encoding: [0x1b,0x28,0x10,0xb4]
pli.b a6, 16
+# CHECK-ASM-AND-OBJ: pli.b a6, -128
+# CHECK-ASM: encoding: [0x1b,0x28,0x80,0xb4]
+pli.b a6, -128
# CHECK-ASM-AND-OBJ: psext.h.b a7, a0
# CHECK-ASM: encoding: [0x9b,0x28,0x45,0xe0]
psext.h.b a7, a0
@@ -373,3 +376,19 @@ ppackt.h t3, s0, s0
# CHECK-ASM-AND-OBJ: packt a2, t3, t1
# CHECK-ASM: encoding: [0x3b,0x46,0x6e,0xb2]
packt a2, t3, t1
+
+# CHECK-ASM-AND-OBJ: pli.dh a4, 16
+# CHECK-ASM: encoding: [0x1b,0x27,0x10,0x30]
+pli.dh a4, 16
+# CHECK-ASM-AND-OBJ: pli.db a6, 16
+# CHECK-ASM: encoding: [0x1b,0x28,0x10,0x34]
+pli.db a6, 16
+# CHECK-ASM-AND-OBJ: pli.db a6, -128
+# CHECK-ASM: encoding: [0x1b,0x28,0x80,0x34]
+pli.db a6, -128
+# CHECK-ASM-AND-OBJ: plui.dh tp, 32
+# CHECK-ASM: encoding: [0x1b,0x22,0x08,0x70]
+plui.dh tp, 32
+# CHECK-ASM-AND-OBJ: plui.dh tp, -412
+# CHECK-ASM: encoding: [0x1b,0x22,0x99,0x70]
+plui.dh tp, 612
diff --git a/llvm/test/MC/RISCV/rv64p-invalid.s b/llvm/test/MC/RISCV/rv64p-invalid.s
index 58f5dfb822dea..e18c9ec0e29ea 100644
--- a/llvm/test/MC/RISCV/rv64p-invalid.s
+++ b/llvm/test/MC/RISCV/rv64p-invalid.s
@@ -65,3 +65,8 @@ mulsu.h00 a4, s4, s6 # CHECK: :[[@LINE]]:1: error: instruction requires the foll
maccsu.h00 s4, s4, s0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: RV32I Base Instruction Set
mulsu.h11 s8, s4, s0 # CHECK: :[[@LINE]]:1: error: instruction requires the following: RV32I Base Instruction Set
maccsu.h11 s0, a2, s6 # CHECK: :[[@LINE]]:1: error: instruction requires the following: RV32I Base Instruction Set
+
+# FIXME: This error doesn't make sense. Should say that we need RV32I.
+pli.dh a0, 1 # CHECK: :[[@LINE]]:8: error: invalid operand for instruction
+pli.db s0, 1 # CHECK: :[[@LINE]]:8: error: invalid operand for instruction
+plui.dh t1, 1 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction
diff --git a/llvm/test/MC/RISCV/rv64p-valid.s b/llvm/test/MC/RISCV/rv64p-valid.s
index 5e0b22759abf4..f5dd85f2d338a 100644
--- a/llvm/test/MC/RISCV/rv64p-valid.s
+++ b/llvm/test/MC/RISCV/rv64p-valid.s
@@ -79,6 +79,12 @@ pli.w a5, 5
# CHECK-ASM-AND-OBJ: pli.b a6, 6
# CHECK-ASM: encoding: [0x1b,0x28,0x06,0xb4]
pli.b a6, 6
+# CHECK-ASM-AND-OBJ: pli.b a6, -1
+# CHECK-ASM: encoding: [0x1b,0x28,0xff,0xb4]
+pli.b a6, -1
+# CHECK-ASM-AND-OBJ: pli.b a6, -1
+# CHECK-ASM: encoding: [0x1b,0x28,0xff,0xb4]
+pli.b a6, 255
# CHECK-ASM-AND-OBJ: psext.h.b t3, a2
# CHECK-ASM: encoding: [0x1b,0x2e,0x46,0xe0]
psext.h.b t3, a2
``````````
</details>
https://github.com/llvm/llvm-project/pull/153972
More information about the llvm-commits
mailing list