[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