[llvm] [llvm][RISCV] Support P Extension CodeGen (PR #167895)

Brandon Wu via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 20 22:47:27 PST 2025


https://github.com/4vtomat updated https://github.com/llvm/llvm-project/pull/167895

>From 7e7f3b952af806c912298a7540dd9e2ca5291cd9 Mon Sep 17 00:00:00 2001
From: Brandon Wu <songwu0813 at gmail.com>
Date: Mon, 3 Nov 2025 01:56:26 -0800
Subject: [PATCH 1/5] [llvm][RISCV] Support P Extension CodeGen

This patch supports: PSLLI_B, PSLLI_H, PSLLI_W, PSSLAI_H and PSSLAI_W
---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp |  1 +
 llvm/lib/Target/RISCV/RISCVInstrInfoP.td    | 21 ++++++++
 llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll     | 43 ++++++++++++++++
 llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll     | 57 +++++++++++++++++++++
 4 files changed, 122 insertions(+)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 28fe76bb35b0c..871b7d2991451 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -523,6 +523,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::SADDSAT, VTs, Legal);
     setOperationAction(ISD::USUBSAT, VTs, Legal);
     setOperationAction(ISD::SSUBSAT, VTs, Legal);
+    setOperationAction(ISD::SSHLSAT, VTs, Legal);
     setOperationAction({ISD::AVGFLOORS, ISD::AVGFLOORU}, VTs, Legal);
     setOperationAction({ISD::ABDS, ISD::ABDU}, VTs, Legal);
     setOperationAction(ISD::BUILD_VECTOR, VTs, Custom);
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index 7637047aabf2d..1e2afcbbcb51c 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -19,6 +19,8 @@
 //===----------------------------------------------------------------------===//
 
 def simm10 : RISCVSImmOp<10>, TImmLeaf<XLenVT, "return isInt<10>(Imm);">;
+def tuimm3 : RISCVUImmOp<3>, TImmLeaf<XLenVT, "return isUInt<3>(Imm);">;
+def tuimm4 : RISCVUImmOp<4>, TImmLeaf<XLenVT, "return isUInt<4>(Imm);">;
 
 def SImm8UnsignedAsmOperand : SImmAsmOperand<8, "Unsigned"> {
   let RenderMethod = "addSImm8UnsignedOperands";
@@ -1517,6 +1519,17 @@ let Predicates = [HasStdExtP] in {
   def: Pat<(XLenVecI16VT (abds GPR:$rs1, GPR:$rs2)), (PDIF_H GPR:$rs1, GPR:$rs2)>;
   def: Pat<(XLenVecI16VT (abdu GPR:$rs1, GPR:$rs2)), (PDIFU_H GPR:$rs1, GPR:$rs2)>;
   
+  // 8-bit logical shift left patterns
+  def: Pat<(XLenVecI8VT (shl GPR:$rs1, (XLenVecI8VT (riscv_pli tuimm3:$shamt)))),
+           (PSLLI_B GPR:$rs1, tuimm3:$shamt)>;
+
+  // 16-bit logical shift left patterns
+  def: Pat<(XLenVecI16VT (shl GPR:$rs1, (XLenVecI16VT (riscv_pli tuimm4:$shamt)))),
+           (PSLLI_H GPR:$rs1, tuimm4:$shamt)>;
+
+  // 16-bit signed saturation shift left patterns
+  def: Pat<(XLenVecI16VT (sshlsat GPR:$rs1, (XLenVecI16VT (riscv_pli tuimm4:$shamt)))),
+           (PSSLAI_H GPR:$rs1, tuimm4:$shamt)>;
 
   // 8-bit PLI SD node pattern
   def: Pat<(XLenVecI8VT (riscv_pli simm8_unsigned:$imm8)), (PLI_B simm8_unsigned:$imm8)>;
@@ -1543,6 +1556,14 @@ let Predicates = [HasStdExtP, IsRV64] in {
   def: Pat<(v2i32 (riscv_pasub GPR:$rs1, GPR:$rs2)), (PASUB_W GPR:$rs1, GPR:$rs2)>;
   def: Pat<(v2i32 (riscv_pasubu GPR:$rs1, GPR:$rs2)), (PASUBU_W GPR:$rs1, GPR:$rs2)>;
 
+  // 32-bit logical shift left patterns
+  def: Pat<(v2i32 (shl GPR:$rs1, (v2i32 (riscv_pli tuimm4:$shamt)))),
+           (PSLLI_W GPR:$rs1, tuimm4:$shamt)>;
+
+  // 32-bit signed saturation shift left patterns
+  def: Pat<(v2i32 (sshlsat GPR:$rs1, (v2i32 (riscv_pli tuimm4:$shamt)))),
+           (PSSLAI_W GPR:$rs1, tuimm4:$shamt)>;
+
   // Load/Store patterns
   def : StPat<store, SD, GPR, v8i8>;
   def : StPat<store, SD, GPR, v4i16>;
diff --git a/llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll b/llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll
index 46d5e9f9a538f..67eb358437d3b 100644
--- a/llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll
+++ b/llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll
@@ -496,6 +496,48 @@ define void @test_extract_vector_8(ptr %ret_ptr, ptr %a_ptr) {
   ret void
 }
 
+; Test logical shift left immediate for v2i16
+define void @test_pslli_h(ptr %ret_ptr, ptr %a_ptr) {
+; CHECK-LABEL: test_pslli_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a1, 0(a1)
+; CHECK-NEXT:    pslli.h a1, a1, 2
+; CHECK-NEXT:    sw a1, 0(a0)
+; CHECK-NEXT:    ret
+  %a = load <2 x i16>, ptr %a_ptr
+  %res = shl <2 x i16> %a, splat(i16 2)
+  store <2 x i16> %res, ptr %ret_ptr
+  ret void
+}
+
+; Test logical shift left immediate for v4i8
+define void @test_pslli_b(ptr %ret_ptr, ptr %a_ptr) {
+; CHECK-LABEL: test_pslli_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a1, 0(a1)
+; CHECK-NEXT:    pslli.b a1, a1, 2
+; CHECK-NEXT:    sw a1, 0(a0)
+; CHECK-NEXT:    ret
+  %a = load <4 x i8>, ptr %a_ptr
+  %res = shl <4 x i8> %a, splat(i8 2)
+  store <4 x i8> %res, ptr %ret_ptr
+  ret void
+}
+
+; Test arithmetic saturation shift left immediate for v2i16
+define void @test_psslai_h(ptr %ret_ptr, ptr %a_ptr) {
+; CHECK-LABEL: test_psslai_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    lw a1, 0(a1)
+; CHECK-NEXT:    psslai.h a1, a1, 2
+; CHECK-NEXT:    sw a1, 0(a0)
+; CHECK-NEXT:    ret
+  %a = load <2 x i16>, ptr %a_ptr
+  %res = call <2 x i16> @llvm.sshl.sat.v2i16(<2 x i16> %a, <2 x i16> splat(i16 2))
+  store <2 x i16> %res, ptr %ret_ptr
+  ret void
+}
+
 ; Intrinsic declarations
 declare <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16>, <2 x i16>)
 declare <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16>, <2 x i16>)
@@ -513,3 +555,4 @@ declare <4 x i8> @llvm.smin.v4i8(<4 x i8>, <4 x i8>)
 declare <4 x i8> @llvm.smax.v4i8(<4 x i8>, <4 x i8>)
 declare <4 x i8> @llvm.umin.v4i8(<4 x i8>, <4 x i8>)
 declare <4 x i8> @llvm.umax.v4i8(<4 x i8>, <4 x i8>)
+declare <2 x i16> @llvm.sshl.sat.v2i16(<2 x i16> %a, <2 x i16> %b)
diff --git a/llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll b/llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll
index 000a95fb6e0f8..6c4a104b0a424 100644
--- a/llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll
+++ b/llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll
@@ -495,6 +495,62 @@ define void @test_extract_vector_32(ptr %ret_ptr, ptr %a_ptr) {
   ret void
 }
 
+; Test logical shift left immediate for v4i16
+define void @test_pslli_h(ptr %ret_ptr, ptr %a_ptr) {
+; CHECK-LABEL: test_pslli_h:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    ld a1, 0(a1)
+; CHECK-NEXT:    pslli.h a1, a1, 2
+; CHECK-NEXT:    sd a1, 0(a0)
+; CHECK-NEXT:    ret
+  %a = load <4 x i16>, ptr %a_ptr
+  %res = shl <4 x i16> %a, splat(i16 2)
+  store <4 x i16> %res, ptr %ret_ptr
+  ret void
+}
+
+; Test logical shift left immediate for v8i8
+define void @test_pslli_b(ptr %ret_ptr, ptr %a_ptr) {
+; CHECK-LABEL: test_pslli_b:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    ld a1, 0(a1)
+; CHECK-NEXT:    pslli.b a1, a1, 2
+; CHECK-NEXT:    sd a1, 0(a0)
+; CHECK-NEXT:    ret
+  %a = load <8 x i8>, ptr %a_ptr
+  %res = shl <8 x i8> %a, splat(i8 2)
+  store <8 x i8> %res, ptr %ret_ptr
+  ret void
+}
+
+; Test logical shift left immediate for v2i32
+define void @test_pslli_w(ptr %ret_ptr, ptr %a_ptr) {
+; CHECK-LABEL: test_pslli_w:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    ld a1, 0(a1)
+; CHECK-NEXT:    pslli.w a1, a1, 2
+; CHECK-NEXT:    sd a1, 0(a0)
+; CHECK-NEXT:    ret
+  %a = load <2 x i32>, ptr %a_ptr
+  %res = shl <2 x i32> %a, splat(i32 2)
+  store <2 x i32> %res, ptr %ret_ptr
+  ret void
+}
+
+; Test arithmetic saturation shift left immediate for v2i32
+define void @test_psslai_w(ptr %ret_ptr, ptr %a_ptr) {
+; CHECK-LABEL: test_psslai_w:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    ld a1, 0(a1)
+; CHECK-NEXT:    psslai.w a1, a1, 2
+; CHECK-NEXT:    sd a1, 0(a0)
+; CHECK-NEXT:    ret
+  %a = load <2 x i32>, ptr %a_ptr
+  %res = call <2 x i32> @llvm.sshl.sat.v2i32(<2 x i32> %a, <2 x i32> splat(i32 2))
+  store <2 x i32> %res, ptr %ret_ptr
+  ret void
+}
+
 ; Intrinsic declarations
 declare <4 x i16> @llvm.sadd.sat.v4i16(<4 x i16>, <4 x i16>)
 declare <4 x i16> @llvm.uadd.sat.v4i16(<4 x i16>, <4 x i16>)
@@ -512,3 +568,4 @@ declare <8 x i8> @llvm.smin.v8i8(<8 x i8>, <8 x i8>)
 declare <8 x i8> @llvm.smax.v8i8(<8 x i8>, <8 x i8>)
 declare <8 x i8> @llvm.umin.v8i8(<8 x i8>, <8 x i8>)
 declare <8 x i8> @llvm.umax.v8i8(<8 x i8>, <8 x i8>)
+declare <2 x i32> @llvm.sshl.sat.v2i32(<2 x i32> %a, <2 x i32> %b)

>From 8abd96236079691d28d72a091d18cf0a3db45d34 Mon Sep 17 00:00:00 2001
From: Brandon Wu <songwu0813 at gmail.com>
Date: Thu, 13 Nov 2025 23:19:19 -0800
Subject: [PATCH 2/5] fixup! shamt

---
 llvm/lib/Target/RISCV/RISCVInstrInfoP.td | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index 1e2afcbbcb51c..b048d7f14457a 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -21,6 +21,7 @@
 def simm10 : RISCVSImmOp<10>, TImmLeaf<XLenVT, "return isInt<10>(Imm);">;
 def tuimm3 : RISCVUImmOp<3>, TImmLeaf<XLenVT, "return isUInt<3>(Imm);">;
 def tuimm4 : RISCVUImmOp<4>, TImmLeaf<XLenVT, "return isUInt<4>(Imm);">;
+def tuimm5 : RISCVUImmOp<5>, TImmLeaf<XLenVT, "return isUInt<5>(Imm);">;
 
 def SImm8UnsignedAsmOperand : SImmAsmOperand<8, "Unsigned"> {
   let RenderMethod = "addSImm8UnsignedOperands";
@@ -1557,8 +1558,8 @@ let Predicates = [HasStdExtP, IsRV64] in {
   def: Pat<(v2i32 (riscv_pasubu GPR:$rs1, GPR:$rs2)), (PASUBU_W GPR:$rs1, GPR:$rs2)>;
 
   // 32-bit logical shift left patterns
-  def: Pat<(v2i32 (shl GPR:$rs1, (v2i32 (riscv_pli tuimm4:$shamt)))),
-           (PSLLI_W GPR:$rs1, tuimm4:$shamt)>;
+  def: Pat<(v2i32 (shl GPR:$rs1, (v2i32 (riscv_pli tuimm5:$shamt)))),
+           (PSLLI_W GPR:$rs1, tuimm5:$shamt)>;
 
   // 32-bit signed saturation shift left patterns
   def: Pat<(v2i32 (sshlsat GPR:$rs1, (v2i32 (riscv_pli tuimm4:$shamt)))),

>From 56ab07f4d2a977a2d1cda1b5658588b4d4d99a48 Mon Sep 17 00:00:00 2001
From: Brandon Wu <songwu0813 at gmail.com>
Date: Thu, 13 Nov 2025 23:22:21 -0800
Subject: [PATCH 3/5] fixup! remove declare

---
 llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll | 1 -
 llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll | 1 -
 2 files changed, 2 deletions(-)

diff --git a/llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll b/llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll
index 67eb358437d3b..2f6596c39b6c0 100644
--- a/llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll
+++ b/llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll
@@ -555,4 +555,3 @@ declare <4 x i8> @llvm.smin.v4i8(<4 x i8>, <4 x i8>)
 declare <4 x i8> @llvm.smax.v4i8(<4 x i8>, <4 x i8>)
 declare <4 x i8> @llvm.umin.v4i8(<4 x i8>, <4 x i8>)
 declare <4 x i8> @llvm.umax.v4i8(<4 x i8>, <4 x i8>)
-declare <2 x i16> @llvm.sshl.sat.v2i16(<2 x i16> %a, <2 x i16> %b)
diff --git a/llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll b/llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll
index 6c4a104b0a424..f4a18ef9fe0d4 100644
--- a/llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll
+++ b/llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll
@@ -568,4 +568,3 @@ declare <8 x i8> @llvm.smin.v8i8(<8 x i8>, <8 x i8>)
 declare <8 x i8> @llvm.smax.v8i8(<8 x i8>, <8 x i8>)
 declare <8 x i8> @llvm.umin.v8i8(<8 x i8>, <8 x i8>)
 declare <8 x i8> @llvm.umax.v8i8(<8 x i8>, <8 x i8>)
-declare <2 x i32> @llvm.sshl.sat.v2i32(<2 x i32> %a, <2 x i32> %b)

>From 91ddd90fdbf473e52d5b037b7f0e18fb08b7413d Mon Sep 17 00:00:00 2001
From: Brandon Wu <songwu0813 at gmail.com>
Date: Thu, 13 Nov 2025 23:48:29 -0800
Subject: [PATCH 4/5] fixup! redeclaration

---
 llvm/lib/Target/RISCV/RISCVInstrInfoP.td | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index b048d7f14457a..b46728f1673c8 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -21,7 +21,6 @@
 def simm10 : RISCVSImmOp<10>, TImmLeaf<XLenVT, "return isInt<10>(Imm);">;
 def tuimm3 : RISCVUImmOp<3>, TImmLeaf<XLenVT, "return isUInt<3>(Imm);">;
 def tuimm4 : RISCVUImmOp<4>, TImmLeaf<XLenVT, "return isUInt<4>(Imm);">;
-def tuimm5 : RISCVUImmOp<5>, TImmLeaf<XLenVT, "return isUInt<5>(Imm);">;
 
 def SImm8UnsignedAsmOperand : SImmAsmOperand<8, "Unsigned"> {
   let RenderMethod = "addSImm8UnsignedOperands";

>From 677001ce51a247b976ea29f72d083f1d33c9da6c Mon Sep 17 00:00:00 2001
From: Brandon Wu <songwu0813 at gmail.com>
Date: Fri, 14 Nov 2025 19:45:02 -0800
Subject: [PATCH 5/5] fixup! tuimm5

---
 llvm/lib/Target/RISCV/RISCVInstrInfoP.td | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index 3ede493aecce7..7cd7ea135a3b8 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -1575,8 +1575,8 @@ let Predicates = [HasStdExtP, IsRV64] in {
            (PSLLI_W GPR:$rs1, tuimm5:$shamt)>;
 
   // 32-bit signed saturation shift left patterns
-  def: Pat<(v2i32 (sshlsat GPR:$rs1, (v2i32 (riscv_pli tuimm4:$shamt)))),
-           (PSSLAI_W GPR:$rs1, tuimm4:$shamt)>;
+  def: Pat<(v2i32 (sshlsat GPR:$rs1, (v2i32 (riscv_pli tuimm5:$shamt)))),
+           (PSSLAI_W GPR:$rs1, tuimm5:$shamt)>;
 
   // Load/Store patterns
   def : StPat<store, SD, GPR, v8i8>;



More information about the llvm-commits mailing list