[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