[llvm] [RISCV][P-ext] Add splat_vector for 64-bit vectors on RV32. (PR #197345)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Tue May 12 21:04:08 PDT 2026


https://github.com/topperc updated https://github.com/llvm/llvm-project/pull/197345

>From 6cc312a4a09463deb78cc8529fa44f9913145531 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Tue, 12 May 2026 17:27:06 -0700
Subject: [PATCH 1/4] [RISCV][P-ext] Add splat_vector for 64-bit vectors on
 RV32.

---
 llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp |  19 +--
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp |   1 +
 llvm/lib/Target/RISCV/RISCVInstrInfoP.td    |  16 ++-
 llvm/test/CodeGen/RISCV/rvp-simd-64.ll      | 130 ++++----------------
 4 files changed, 51 insertions(+), 115 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 777a833ddd3ba..5c14da51ad276 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -2958,9 +2958,12 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
     if (!ConstNode)
       break;
 
+    bool IsDoubleWide = Subtarget->isPExtPackedDoubleType(VT);
+
     if (ConstNode->isZero()) {
+      MCPhysReg X0Reg = IsDoubleWide ? RISCV::X0_Pair : RISCV::X0;
       SDValue New =
-          CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, RISCV::X0, VT);
+          CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, X0Reg, VT);
       ReplaceNode(Node, New.getNode());
       return;
     }
@@ -2969,7 +2972,7 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
     APInt Val = ConstNode->getAPIntValue().trunc(EltSize);
 
     // Use LI for all ones since it can be compressed to c.li.
-    if (Val.isAllOnes()) {
+    if (Val.isAllOnes() && !IsDoubleWide) {
       SDNode *NewNode = CurDAG->getMachineNode(
           RISCV::ADDI, DL, VT, CurDAG->getRegister(RISCV::X0, VT),
           CurDAG->getAllOnesConstant(DL, XLenVT, /*IsTarget=*/true));
@@ -2988,13 +2991,15 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
 
     unsigned Opc = 0;
     if (EltSize == 8) {
-      Opc = RISCV::PLI_B;
-    } else if (isInt<10>(Imm)) {
-      Opc = EltSize == 32 ? RISCV::PLI_W : RISCV::PLI_H;
+      Opc = IsDoubleWide ? RISCV::PLI_DB : RISCV::PLI_B;
+    } else if (EltSize == 16 && isInt<10>(Imm)) {
+      Opc = IsDoubleWide ? RISCV::PLI_DH : RISCV::PLI_H;
+    } else if (!IsDoubleWide && EltSize == 32 && isInt<10>(Imm)) {
+      Opc = RISCV::PLI_W;
     } else if (EltSize == 16 && isShiftedInt<10, 6>(Imm)) {
-      Opc = RISCV::PLUI_H;
+      Opc = IsDoubleWide ? RISCV::PLUI_DH : RISCV::PLUI_H;
       Imm = Imm >> 6;
-    } else if (EltSize == 32 && isShiftedInt<10, 22>(Imm)) {
+    } else if (!IsDoubleWide && EltSize == 32 && isShiftedInt<10, 22>(Imm)) {
       Opc = RISCV::PLUI_W;
       Imm = Imm >> 22;
     }
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index ac1ef084d1d24..2586390d1b1d7 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -629,6 +629,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
       setOperationAction({ISD::AVGFLOORS, ISD::AVGFLOORU}, P64VecVTs, Legal);
       setOperationAction({ISD::SMIN, ISD::UMIN, ISD::SMAX, ISD::UMAX},
                          P64VecVTs, Legal);
+      setOperationAction(ISD::SPLAT_VECTOR, P64VecVTs, Legal);
       setOperationAction(ISD::BUILD_VECTOR, MVT::v2i32, Legal);
       setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v2i32, Legal);
       setOperationAction(ISD::CONCAT_VECTORS, {MVT::v4i16, MVT::v8i8}, Legal);
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index 3f5508f5df4e8..4c8c288657b16 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -2095,8 +2095,10 @@ let Predicates = [HasStdExtP] in {
   def : PatGprShiftMask<riscv_psra, PSRA_HS, shiftMask16, XLenVecI16VT>;
 
   // // splat pattern
-  def : Pat<(XLenVecI8VT (splat_vector (XLenVT GPR:$rs2))), (PADD_BS (XLenVT X0), GPR:$rs2)>;
-  def : Pat<(XLenVecI16VT (splat_vector (XLenVT GPR:$rs2))), (PADD_HS (XLenVT X0), GPR:$rs2)>;
+  def : Pat<(XLenVecI8VT (splat_vector (XLenVT GPR:$rs2))),
+            (PADD_BS (XLenVecI8VT X0), GPR:$rs2)>;
+  def : Pat<(XLenVecI16VT (splat_vector (XLenVT GPR:$rs2))),
+            (PADD_HS (XLenVecI16VT X0), GPR:$rs2)>;
 
   // 8/16-bit comparison patterns (result is all 1s or all 0s per element)
   // a == b
@@ -2271,6 +2273,14 @@ let Predicates = [HasStdExtP, IsRV32] in {
   def : PatGprPairGprPair<umax, PMAXU_DH, v4i16>;
   def : PatGprPairGprPair<smax, PMAX_DW, v2i32>;
   def : PatGprPairGprPair<umax, PMAXU_DW, v2i32>;
+
+  // splat pattern
+  def : Pat<(v8i8 (splat_vector (XLenVT GPR:$rs2))),
+            (PADD_DBS (v8i8 X0_Pair), GPR:$rs2)>;
+  def : Pat<(v4i16 (splat_vector (XLenVT GPR:$rs2))),
+            (PADD_DHS (v4i16 X0_Pair), GPR:$rs2)>;
+  def : Pat<(v2i32 (splat_vector (XLenVT GPR:$rs2))),
+            (PADD_DWS (v2i32 X0_Pair), GPR:$rs2)>;
 } // Predicates = [HasStdExtP, IsRV32]
 
 let Predicates = [HasStdExtP, IsRV64] in {
@@ -2380,7 +2390,7 @@ let Predicates = [HasStdExtP, IsRV64] in {
   def : PatGprShiftMask<riscv_psra, PSRA_WS, shiftMask32, v2i32>;
 
   // splat pattern
-  def : Pat<(v2i32 (splat_vector (XLenVT GPR:$rs2))), (PADD_WS (XLenVT X0), GPR:$rs2)>;
+  def : Pat<(v2i32 (splat_vector (XLenVT GPR:$rs2))), (PADD_WS (v2i32 X0), GPR:$rs2)>;
 
   // 32-bit comparison patterns (result is all 1s or all 0s per element)
   // a == b
diff --git a/llvm/test/CodeGen/RISCV/rvp-simd-64.ll b/llvm/test/CodeGen/RISCV/rvp-simd-64.ll
index 6c6ee5ebcf6a8..f794129ff16c4 100644
--- a/llvm/test/CodeGen/RISCV/rvp-simd-64.ll
+++ b/llvm/test/CodeGen/RISCV/rvp-simd-64.ll
@@ -1022,9 +1022,7 @@ define <8 x i8> @test_paaddu_b(<8 x i8> %a, <8 x i8> %b) {
 define <2 x i32> @test_pabs_w(<2 x i32> %a) {
 ; RV32-LABEL: test_pabs_w:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    li a2, 0
-; RV32-NEXT:    li a3, 0
-; RV32-NEXT:    psub.dw a2, a2, a0
+; RV32-NEXT:    pneg.dw a2, a0
 ; RV32-NEXT:    pmax.dw a0, a0, a2
 ; RV32-NEXT:    ret
 ;
@@ -1040,11 +1038,7 @@ define <2 x i32> @test_pabs_w(<2 x i32> %a) {
 define <4 x i16> @test_pabs_h(<4 x i16> %a) {
 ; RV32-LABEL: test_pabs_h:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    lui a2, %hi(.LCPI38_0)
-; RV32-NEXT:    lw a4, %lo(.LCPI38_0)(a2)
-; RV32-NEXT:    addi a2, a2, %lo(.LCPI38_0)
-; RV32-NEXT:    lw a5, 4(a2)
-; RV32-NEXT:    psub.dh a2, a4, a0
+; RV32-NEXT:    pneg.dh a2, a0
 ; RV32-NEXT:    pmax.dh a0, a0, a2
 ; RV32-NEXT:    ret
 ;
@@ -1059,11 +1053,7 @@ define <4 x i16> @test_pabs_h(<4 x i16> %a) {
 define <8 x i8> @test_pabs_b(<8 x i8> %a) {
 ; RV32-LABEL: test_pabs_b:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    lui a2, %hi(.LCPI39_0)
-; RV32-NEXT:    lw a4, %lo(.LCPI39_0)(a2)
-; RV32-NEXT:    addi a2, a2, %lo(.LCPI39_0)
-; RV32-NEXT:    lw a5, 4(a2)
-; RV32-NEXT:    psub.db a2, a4, a0
+; RV32-NEXT:    pneg.db a2, a0
 ; RV32-NEXT:    pmax.db a0, a0, a2
 ; RV32-NEXT:    ret
 ;
@@ -1279,10 +1269,7 @@ define <8 x i8> @test_pasubu_b(<8 x i8> %a, <8 x i8> %b) {
 define <4 x i16> @test_pli_h() {
 ; RV32-LABEL: test_pli_h:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    lui a1, %hi(.LCPI50_0)
-; RV32-NEXT:    lw a0, %lo(.LCPI50_0)(a1)
-; RV32-NEXT:    addi a1, a1, %lo(.LCPI50_0)
-; RV32-NEXT:    lw a1, 4(a1)
+; RV32-NEXT:    pli.dh a0, 100
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_pli_h:
@@ -1295,8 +1282,7 @@ define <4 x i16> @test_pli_h() {
 define <2 x i32> @test_pli_h_v2i32() {
 ; RV32-LABEL: test_pli_h_v2i32:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    pli.h a0, 100
-; RV32-NEXT:    pli.h a1, 100
+; RV32-NEXT:    pli.dh a0, 100
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_pli_h_v2i32:
@@ -1310,10 +1296,7 @@ define <2 x i32> @test_pli_h_v2i32() {
 define <8 x i8> @test_pli_b() {
 ; RV32-LABEL: test_pli_b:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    lui a1, %hi(.LCPI52_0)
-; RV32-NEXT:    lw a0, %lo(.LCPI52_0)(a1)
-; RV32-NEXT:    addi a1, a1, %lo(.LCPI52_0)
-; RV32-NEXT:    lw a1, 4(a1)
+; RV32-NEXT:    pli.db a0, 64
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_pli_b:
@@ -1326,10 +1309,7 @@ define <8 x i8> @test_pli_b() {
 define <4 x i16> @test_pli_b_v4i16() {
 ; RV32-LABEL: test_pli_b_v4i16:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    lui a1, %hi(.LCPI53_0)
-; RV32-NEXT:    lw a0, %lo(.LCPI53_0)(a1)
-; RV32-NEXT:    addi a1, a1, %lo(.LCPI53_0)
-; RV32-NEXT:    lw a1, 4(a1)
+; RV32-NEXT:    pli.db a0, 64
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_pli_b_v4i16:
@@ -1342,8 +1322,7 @@ define <4 x i16> @test_pli_b_v4i16() {
 define <2 x i32> @test_pli_b_v2i32() {
 ; RV32-LABEL: test_pli_b_v2i32:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    pli.b a0, 64
-; RV32-NEXT:    pli.b a1, 64
+; RV32-NEXT:    pli.db a0, 64
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_pli_b_v2i32:
@@ -1358,7 +1337,7 @@ define <2 x i32> @test_pli_w() {
 ; RV32-LABEL: test_pli_w:
 ; RV32:       # %bb.0:
 ; RV32-NEXT:    li a0, -256
-; RV32-NEXT:    li a1, -256
+; RV32-NEXT:    pmv.dws a0, a0
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_pli_w:
@@ -1371,10 +1350,7 @@ define <2 x i32> @test_pli_w() {
 define <4 x i16> @test_plui_h() {
 ; RV32-LABEL: test_plui_h:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    lui a1, %hi(.LCPI56_0)
-; RV32-NEXT:    lw a0, %lo(.LCPI56_0)(a1)
-; RV32-NEXT:    addi a1, a1, %lo(.LCPI56_0)
-; RV32-NEXT:    lw a1, 4(a1)
+; RV32-NEXT:    plui.dh a0, 100
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_plui_h:
@@ -1387,10 +1363,7 @@ define <4 x i16> @test_plui_h() {
 define <4 x i16> @test_plui_h_negative() {
 ; RV32-LABEL: test_plui_h_negative:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    lui a1, %hi(.LCPI57_0)
-; RV32-NEXT:    lw a0, %lo(.LCPI57_0)(a1)
-; RV32-NEXT:    addi a1, a1, %lo(.LCPI57_0)
-; RV32-NEXT:    lw a1, 4(a1)
+; RV32-NEXT:    plui.dh a0, -412
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_plui_h_negative:
@@ -1403,8 +1376,7 @@ define <4 x i16> @test_plui_h_negative() {
 define <2 x i32> @test_plui_h_v2i32() {
 ; RV32-LABEL: test_plui_h_v2i32:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    plui.h a0, 100
-; RV32-NEXT:    plui.h a1, 100
+; RV32-NEXT:    plui.dh a0, 100
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_plui_h_v2i32:
@@ -1417,8 +1389,7 @@ define <2 x i32> @test_plui_h_v2i32() {
 define <2 x i32> @test_plui_h_negative_v2i32() {
 ; RV32-LABEL: test_plui_h_negative_v2i32:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    plui.h a0, -412
-; RV32-NEXT:    plui.h a1, -412
+; RV32-NEXT:    plui.dh a0, -412
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_plui_h_negative_v2i32:
@@ -1432,7 +1403,7 @@ define <2 x i32> @test_plui_w() {
 ; RV32-LABEL: test_plui_w:
 ; RV32:       # %bb.0:
 ; RV32-NEXT:    lui a0, 76800
-; RV32-NEXT:    lui a1, 76800
+; RV32-NEXT:    pmv.dws a0, a0
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_plui_w:
@@ -1446,7 +1417,7 @@ define <2 x i32> @test_plui_w_negative() {
 ; RV32-LABEL: test_plui_w_negative:
 ; RV32:       # %bb.0:
 ; RV32-NEXT:    lui a0, 825344
-; RV32-NEXT:    lui a1, 825344
+; RV32-NEXT:    pmv.dws a0, a0
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_plui_w_negative:
@@ -1459,10 +1430,7 @@ define <2 x i32> @test_plui_w_negative() {
 define <8 x i8> @test_allones_v8i8() {
 ; RV32-LABEL: test_allones_v8i8:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    lui a1, %hi(.LCPI62_0)
-; RV32-NEXT:    lw a0, %lo(.LCPI62_0)(a1)
-; RV32-NEXT:    addi a1, a1, %lo(.LCPI62_0)
-; RV32-NEXT:    lw a1, 4(a1)
+; RV32-NEXT:    pli.db a0, -1
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_allones_v8i8:
@@ -1475,10 +1443,7 @@ define <8 x i8> @test_allones_v8i8() {
 define <4 x i16> @test_allones_v4i16() {
 ; RV32-LABEL: test_allones_v4i16:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    lui a1, %hi(.LCPI63_0)
-; RV32-NEXT:    lw a0, %lo(.LCPI63_0)(a1)
-; RV32-NEXT:    addi a1, a1, %lo(.LCPI63_0)
-; RV32-NEXT:    lw a1, 4(a1)
+; RV32-NEXT:    pli.db a0, -1
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_allones_v4i16:
@@ -1491,8 +1456,7 @@ define <4 x i16> @test_allones_v4i16() {
 define <2 x i32> @test_allones_v2i32() {
 ; RV32-LABEL: test_allones_v2i32:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    li a0, -1
-; RV32-NEXT:    li a1, -1
+; RV32-NEXT:    pli.db a0, -1
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_allones_v2i32:
@@ -1904,7 +1868,7 @@ define <2 x i32> @test_pasubu_w(<2 x i32> %a, <2 x i32> %b) {
 define <2 x i32> @test_non_const_splat_i32(i32 %elt) {
 ; RV32-LABEL: test_non_const_splat_i32:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    mv a1, a0
+; RV32-NEXT:    pmv.dws a0, a0
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_non_const_splat_i32:
@@ -1920,21 +1884,8 @@ define <2 x i32> @test_non_const_splat_i32(i32 %elt) {
 define <8 x i8> @test_padd_bs_splat_lhs(<8 x i8> %a, i8 %b) {
 ; RV32-LABEL: test_padd_bs_splat_lhs:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    addi sp, sp, -16
-; RV32-NEXT:    .cfi_def_cfa_offset 16
-; RV32-NEXT:    sb a2, 12(sp)
-; RV32-NEXT:    sb a2, 13(sp)
-; RV32-NEXT:    sb a2, 14(sp)
-; RV32-NEXT:    sb a2, 15(sp)
-; RV32-NEXT:    sb a2, 8(sp)
-; RV32-NEXT:    sb a2, 9(sp)
-; RV32-NEXT:    sb a2, 10(sp)
-; RV32-NEXT:    sb a2, 11(sp)
-; RV32-NEXT:    lw a3, 12(sp)
-; RV32-NEXT:    lw a2, 8(sp)
+; RV32-NEXT:    pmv.dbs a2, a2
 ; RV32-NEXT:    padd.db a0, a2, a0
-; RV32-NEXT:    addi sp, sp, 16
-; RV32-NEXT:    .cfi_def_cfa_offset 0
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_padd_bs_splat_lhs:
@@ -1950,21 +1901,8 @@ define <8 x i8> @test_padd_bs_splat_lhs(<8 x i8> %a, i8 %b) {
 define <8 x i8> @test_padd_bs_splat_rhs(<8 x i8> %a, i8 %b) {
 ; RV32-LABEL: test_padd_bs_splat_rhs:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    addi sp, sp, -16
-; RV32-NEXT:    .cfi_def_cfa_offset 16
-; RV32-NEXT:    sb a2, 12(sp)
-; RV32-NEXT:    sb a2, 13(sp)
-; RV32-NEXT:    sb a2, 14(sp)
-; RV32-NEXT:    sb a2, 15(sp)
-; RV32-NEXT:    sb a2, 8(sp)
-; RV32-NEXT:    sb a2, 9(sp)
-; RV32-NEXT:    sb a2, 10(sp)
-; RV32-NEXT:    sb a2, 11(sp)
-; RV32-NEXT:    lw a3, 12(sp)
-; RV32-NEXT:    lw a2, 8(sp)
+; RV32-NEXT:    pmv.dbs a2, a2
 ; RV32-NEXT:    padd.db a0, a0, a2
-; RV32-NEXT:    addi sp, sp, 16
-; RV32-NEXT:    .cfi_def_cfa_offset 0
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_padd_bs_splat_rhs:
@@ -1980,17 +1918,8 @@ define <8 x i8> @test_padd_bs_splat_rhs(<8 x i8> %a, i8 %b) {
 define <4 x i16> @test_padd_hs_splat_lhs(<4 x i16> %a, i16 %b) {
 ; RV32-LABEL: test_padd_hs_splat_lhs:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    addi sp, sp, -16
-; RV32-NEXT:    .cfi_def_cfa_offset 16
-; RV32-NEXT:    sh a2, 8(sp)
-; RV32-NEXT:    sh a2, 10(sp)
-; RV32-NEXT:    sh a2, 12(sp)
-; RV32-NEXT:    sh a2, 14(sp)
-; RV32-NEXT:    lw a3, 12(sp)
-; RV32-NEXT:    lw a2, 8(sp)
+; RV32-NEXT:    pmv.dhs a2, a2
 ; RV32-NEXT:    padd.dh a0, a2, a0
-; RV32-NEXT:    addi sp, sp, 16
-; RV32-NEXT:    .cfi_def_cfa_offset 0
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_padd_hs_splat_lhs:
@@ -2006,17 +1935,8 @@ define <4 x i16> @test_padd_hs_splat_lhs(<4 x i16> %a, i16 %b) {
 define <4 x i16> @test_padd_hs_splat_rhs(<4 x i16> %a, i16 %b) {
 ; RV32-LABEL: test_padd_hs_splat_rhs:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    addi sp, sp, -16
-; RV32-NEXT:    .cfi_def_cfa_offset 16
-; RV32-NEXT:    sh a2, 8(sp)
-; RV32-NEXT:    sh a2, 10(sp)
-; RV32-NEXT:    sh a2, 12(sp)
-; RV32-NEXT:    sh a2, 14(sp)
-; RV32-NEXT:    lw a3, 12(sp)
-; RV32-NEXT:    lw a2, 8(sp)
+; RV32-NEXT:    pmv.dhs a2, a2
 ; RV32-NEXT:    padd.dh a0, a0, a2
-; RV32-NEXT:    addi sp, sp, 16
-; RV32-NEXT:    .cfi_def_cfa_offset 0
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_padd_hs_splat_rhs:
@@ -2032,7 +1952,7 @@ define <4 x i16> @test_padd_hs_splat_rhs(<4 x i16> %a, i16 %b) {
 define <2 x i32> @test_padd_ws_splat_lhs(<2 x i32> %a, i32 %b) {
 ; RV32-LABEL: test_padd_ws_splat_lhs:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    mv a3, a2
+; RV32-NEXT:    pmv.dws a2, a2
 ; RV32-NEXT:    padd.dw a0, a2, a0
 ; RV32-NEXT:    ret
 ;
@@ -2049,7 +1969,7 @@ define <2 x i32> @test_padd_ws_splat_lhs(<2 x i32> %a, i32 %b) {
 define <2 x i32> @test_padd_ws_splat_rhs(<2 x i32> %a, i32 %b) {
 ; RV32-LABEL: test_padd_ws_splat_rhs:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    mv a3, a2
+; RV32-NEXT:    pmv.dws a2, a2
 ; RV32-NEXT:    padd.dw a0, a0, a2
 ; RV32-NEXT:    ret
 ;

>From e08f6cb575d3292b4169a9dabeeb91856e40c247 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Tue, 12 May 2026 20:55:10 -0700
Subject: [PATCH 2/4] fixup! Use buildGPRPair for v2i32

---
 llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 8 ++++++++
 llvm/lib/Target/RISCV/RISCVInstrInfoP.td    | 3 +--
 llvm/test/CodeGen/RISCV/rvp-simd-64.ll      | 6 +++---
 3 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 5c14da51ad276..225a9593263af 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -3011,6 +3011,14 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
       return;
     }
 
+    // Use buildGPRPair for v2i32 on RV32.
+    if (!Subtarget->is64Bit() && VT == MVT::v2i32) {
+      SDValue Pair = buildGPRPair(CurDAG, DL, VT, Node->getOperand(0),
+                                  Node->getOperand(0));
+      ReplaceNode(Node, Pair.getNode());
+      return;
+    }
+
     break;
   }
   case ISD::BUILD_VECTOR: {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index 81b12c1aa1123..b3f9c838bb9c5 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -2289,8 +2289,7 @@ let Predicates = [HasStdExtP, IsRV32] in {
             (PADD_DBS (v8i8 X0_Pair), GPR:$rs2)>;
   def : Pat<(v4i16 (splat_vector (XLenVT GPR:$rs2))),
             (PADD_DHS (v4i16 X0_Pair), GPR:$rs2)>;
-  def : Pat<(v2i32 (splat_vector (XLenVT GPR:$rs2))),
-            (PADD_DWS (v2i32 X0_Pair), GPR:$rs2)>;
+  // v2i32 handled with buildGPRPair in RISCVISelDAGToDAG.cpp
 } // Predicates = [HasStdExtP, IsRV32]
 
 let Predicates = [HasStdExtP, IsRV64] in {
diff --git a/llvm/test/CodeGen/RISCV/rvp-simd-64.ll b/llvm/test/CodeGen/RISCV/rvp-simd-64.ll
index 99f26270c7551..45a5dc49e2d61 100644
--- a/llvm/test/CodeGen/RISCV/rvp-simd-64.ll
+++ b/llvm/test/CodeGen/RISCV/rvp-simd-64.ll
@@ -1327,7 +1327,7 @@ define <2 x i32> @test_pli_w() {
 ; RV32-LABEL: test_pli_w:
 ; RV32:       # %bb.0:
 ; RV32-NEXT:    li a0, -256
-; RV32-NEXT:    pmv.dws a0, a0
+; RV32-NEXT:    li a1, -256
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_pli_w:
@@ -1393,7 +1393,7 @@ define <2 x i32> @test_plui_w() {
 ; RV32-LABEL: test_plui_w:
 ; RV32:       # %bb.0:
 ; RV32-NEXT:    lui a0, 76800
-; RV32-NEXT:    pmv.dws a0, a0
+; RV32-NEXT:    lui a1, 76800
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_plui_w:
@@ -1407,7 +1407,7 @@ define <2 x i32> @test_plui_w_negative() {
 ; RV32-LABEL: test_plui_w_negative:
 ; RV32:       # %bb.0:
 ; RV32-NEXT:    lui a0, 825344
-; RV32-NEXT:    pmv.dws a0, a0
+; RV32-NEXT:    lui a1, 825344
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_plui_w_negative:

>From 0ee919852aaeae50c1eb9eebc30572c43b3a0fd2 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Tue, 12 May 2026 20:56:09 -0700
Subject: [PATCH 3/4] fixup! Fix incomplete change

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

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index b3f9c838bb9c5..81b12c1aa1123 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -2289,7 +2289,8 @@ let Predicates = [HasStdExtP, IsRV32] in {
             (PADD_DBS (v8i8 X0_Pair), GPR:$rs2)>;
   def : Pat<(v4i16 (splat_vector (XLenVT GPR:$rs2))),
             (PADD_DHS (v4i16 X0_Pair), GPR:$rs2)>;
-  // v2i32 handled with buildGPRPair in RISCVISelDAGToDAG.cpp
+  def : Pat<(v2i32 (splat_vector (XLenVT GPR:$rs2))),
+            (PADD_DWS (v2i32 X0_Pair), GPR:$rs2)>;
 } // Predicates = [HasStdExtP, IsRV32]
 
 let Predicates = [HasStdExtP, IsRV64] in {

>From 8acdf9d9014df938b7eb50d2a1307c4a2fc7e3b4 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Tue, 12 May 2026 21:03:50 -0700
Subject: [PATCH 4/4] fixup! Use buildGPRPair for v2i32 for non-constnats

---
 llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 100 ++++++++++----------
 llvm/lib/Target/RISCV/RISCVInstrInfoP.td    |   3 +-
 llvm/test/CodeGen/RISCV/rvp-simd-64.ll      |   6 +-
 3 files changed, 53 insertions(+), 56 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 225a9593263af..39bf77ba9c585 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -2954,61 +2954,59 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
   case ISD::SPLAT_VECTOR: {
     if (!Subtarget->hasStdExtP())
       break;
-    auto *ConstNode = dyn_cast<ConstantSDNode>(Node->getOperand(0));
-    if (!ConstNode)
-      break;
-
-    bool IsDoubleWide = Subtarget->isPExtPackedDoubleType(VT);
-
-    if (ConstNode->isZero()) {
-      MCPhysReg X0Reg = IsDoubleWide ? RISCV::X0_Pair : RISCV::X0;
-      SDValue New =
-          CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, X0Reg, VT);
-      ReplaceNode(Node, New.getNode());
-      return;
-    }
+    if (auto *ConstNode = dyn_cast<ConstantSDNode>(Node->getOperand(0))) {
+      bool IsDoubleWide = Subtarget->isPExtPackedDoubleType(VT);
+
+      if (ConstNode->isZero()) {
+        MCPhysReg X0Reg = IsDoubleWide ? RISCV::X0_Pair : RISCV::X0;
+        SDValue New =
+            CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, X0Reg, VT);
+        ReplaceNode(Node, New.getNode());
+        return;
+      }
 
-    unsigned EltSize = VT.getVectorElementType().getSizeInBits();
-    APInt Val = ConstNode->getAPIntValue().trunc(EltSize);
+      unsigned EltSize = VT.getVectorElementType().getSizeInBits();
+      APInt Val = ConstNode->getAPIntValue().trunc(EltSize);
 
-    // Use LI for all ones since it can be compressed to c.li.
-    if (Val.isAllOnes() && !IsDoubleWide) {
-      SDNode *NewNode = CurDAG->getMachineNode(
-          RISCV::ADDI, DL, VT, CurDAG->getRegister(RISCV::X0, VT),
-          CurDAG->getAllOnesConstant(DL, XLenVT, /*IsTarget=*/true));
-      ReplaceNode(Node, NewNode);
-      return;
-    }
+      // Use LI for all ones since it can be compressed to c.li.
+      if (Val.isAllOnes() && !IsDoubleWide) {
+        SDNode *NewNode = CurDAG->getMachineNode(
+            RISCV::ADDI, DL, VT, CurDAG->getRegister(RISCV::X0, VT),
+            CurDAG->getAllOnesConstant(DL, XLenVT, /*IsTarget=*/true));
+        ReplaceNode(Node, NewNode);
+        return;
+      }
 
-    // Find the smallest splat.
-    if (Val.getBitWidth() > 16 && Val.isSplat(16))
-      Val = Val.trunc(16);
-    if (Val.getBitWidth() > 8 && Val.isSplat(8))
-      Val = Val.trunc(8);
-
-    EltSize = Val.getBitWidth();
-    int64_t Imm = Val.getSExtValue();
-
-    unsigned Opc = 0;
-    if (EltSize == 8) {
-      Opc = IsDoubleWide ? RISCV::PLI_DB : RISCV::PLI_B;
-    } else if (EltSize == 16 && isInt<10>(Imm)) {
-      Opc = IsDoubleWide ? RISCV::PLI_DH : RISCV::PLI_H;
-    } else if (!IsDoubleWide && EltSize == 32 && isInt<10>(Imm)) {
-      Opc = RISCV::PLI_W;
-    } else if (EltSize == 16 && isShiftedInt<10, 6>(Imm)) {
-      Opc = IsDoubleWide ? RISCV::PLUI_DH : RISCV::PLUI_H;
-      Imm = Imm >> 6;
-    } else if (!IsDoubleWide && EltSize == 32 && isShiftedInt<10, 22>(Imm)) {
-      Opc = RISCV::PLUI_W;
-      Imm = Imm >> 22;
-    }
+      // Find the smallest splat.
+      if (Val.getBitWidth() > 16 && Val.isSplat(16))
+        Val = Val.trunc(16);
+      if (Val.getBitWidth() > 8 && Val.isSplat(8))
+        Val = Val.trunc(8);
+
+      EltSize = Val.getBitWidth();
+      int64_t Imm = Val.getSExtValue();
+
+      unsigned Opc = 0;
+      if (EltSize == 8) {
+        Opc = IsDoubleWide ? RISCV::PLI_DB : RISCV::PLI_B;
+      } else if (EltSize == 16 && isInt<10>(Imm)) {
+        Opc = IsDoubleWide ? RISCV::PLI_DH : RISCV::PLI_H;
+      } else if (!IsDoubleWide && EltSize == 32 && isInt<10>(Imm)) {
+        Opc = RISCV::PLI_W;
+      } else if (EltSize == 16 && isShiftedInt<10, 6>(Imm)) {
+        Opc = IsDoubleWide ? RISCV::PLUI_DH : RISCV::PLUI_H;
+        Imm = Imm >> 6;
+      } else if (!IsDoubleWide && EltSize == 32 && isShiftedInt<10, 22>(Imm)) {
+        Opc = RISCV::PLUI_W;
+        Imm = Imm >> 22;
+      }
 
-    if (Opc) {
-      SDNode *NewNode = CurDAG->getMachineNode(
-          Opc, DL, VT, CurDAG->getSignedTargetConstant(Imm, DL, XLenVT));
-      ReplaceNode(Node, NewNode);
-      return;
+      if (Opc) {
+        SDNode *NewNode = CurDAG->getMachineNode(
+            Opc, DL, VT, CurDAG->getSignedTargetConstant(Imm, DL, XLenVT));
+        ReplaceNode(Node, NewNode);
+        return;
+      }
     }
 
     // Use buildGPRPair for v2i32 on RV32.
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index 81b12c1aa1123..168e8e2926fd9 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -2289,8 +2289,7 @@ let Predicates = [HasStdExtP, IsRV32] in {
             (PADD_DBS (v8i8 X0_Pair), GPR:$rs2)>;
   def : Pat<(v4i16 (splat_vector (XLenVT GPR:$rs2))),
             (PADD_DHS (v4i16 X0_Pair), GPR:$rs2)>;
-  def : Pat<(v2i32 (splat_vector (XLenVT GPR:$rs2))),
-            (PADD_DWS (v2i32 X0_Pair), GPR:$rs2)>;
+  // v2i32 on RV32 is handled by buildGPRPair in RISCVISelDAGToDAG.cpp
 } // Predicates = [HasStdExtP, IsRV32]
 
 let Predicates = [HasStdExtP, IsRV64] in {
diff --git a/llvm/test/CodeGen/RISCV/rvp-simd-64.ll b/llvm/test/CodeGen/RISCV/rvp-simd-64.ll
index 45a5dc49e2d61..e7d80a59ae059 100644
--- a/llvm/test/CodeGen/RISCV/rvp-simd-64.ll
+++ b/llvm/test/CodeGen/RISCV/rvp-simd-64.ll
@@ -1858,7 +1858,7 @@ define <2 x i32> @test_pasubu_w(<2 x i32> %a, <2 x i32> %b) {
 define <2 x i32> @test_non_const_splat_i32(i32 %elt) {
 ; RV32-LABEL: test_non_const_splat_i32:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    pmv.dws a0, a0
+; RV32-NEXT:    mv a1, a0
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: test_non_const_splat_i32:
@@ -1942,7 +1942,7 @@ define <4 x i16> @test_padd_hs_splat_rhs(<4 x i16> %a, i16 %b) {
 define <2 x i32> @test_padd_ws_splat_lhs(<2 x i32> %a, i32 %b) {
 ; RV32-LABEL: test_padd_ws_splat_lhs:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    pmv.dws a2, a2
+; RV32-NEXT:    mv a3, a2
 ; RV32-NEXT:    padd.dw a0, a2, a0
 ; RV32-NEXT:    ret
 ;
@@ -1959,7 +1959,7 @@ define <2 x i32> @test_padd_ws_splat_lhs(<2 x i32> %a, i32 %b) {
 define <2 x i32> @test_padd_ws_splat_rhs(<2 x i32> %a, i32 %b) {
 ; RV32-LABEL: test_padd_ws_splat_rhs:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    pmv.dws a2, a2
+; RV32-NEXT:    mv a3, a2
 ; RV32-NEXT:    padd.dw a0, a0, a2
 ; RV32-NEXT:    ret
 ;



More information about the llvm-commits mailing list