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

This patch supports: PSLLI_B, PSLLI_H, PSLLI_W, PSSLAI_H and PSSLAI_W
This commit is contained in:
Brandon Wu
2025-11-26 11:10:28 +08:00
committed by GitHub
parent 175168c620
commit 40f21a7b2f
4 changed files with 117 additions and 0 deletions

View File

@@ -525,6 +525,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::SPLAT_VECTOR, VTs, Legal);

View File

@@ -1520,6 +1520,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 (splat_vector uimm3:$shamt)))),
(PSLLI_B GPR:$rs1, uimm3:$shamt)>;
// 16-bit logical shift left patterns
def: Pat<(XLenVecI16VT (shl GPR:$rs1, (XLenVecI16VT (splat_vector uimm4:$shamt)))),
(PSLLI_H GPR:$rs1, uimm4:$shamt)>;
// 16-bit signed saturation shift left patterns
def: Pat<(XLenVecI16VT (sshlsat GPR:$rs1, (XLenVecI16VT (splat_vector uimm4:$shamt)))),
(PSSLAI_H GPR:$rs1, uimm4:$shamt)>;
// 8-bit PLI SD node pattern
def: Pat<(XLenVecI8VT (splat_vector simm8_unsigned:$imm8)), (PLI_B simm8_unsigned:$imm8)>;
@@ -1570,6 +1581,14 @@ let Predicates = [HasStdExtP, IsRV64] in {
// splat pattern
def: Pat<(v2i32 (splat_vector (XLenVT GPR:$rs2))), (PADD_WS (XLenVT X0), GPR:$rs2)>;
// 32-bit logical shift left patterns
def: Pat<(v2i32 (shl GPR:$rs1, (v2i32 (splat_vector uimm5:$shamt)))),
(PSLLI_W GPR:$rs1, uimm5:$shamt)>;
// 32-bit signed saturation shift left patterns
def: Pat<(v2i32 (sshlsat GPR:$rs1, (v2i32 (splat_vector uimm5:$shamt)))),
(PSSLAI_W GPR:$rs1, uimm5:$shamt)>;
// Load/Store patterns
def : StPat<store, SD, GPR, v8i8>;
def : StPat<store, SD, GPR, v4i16>;

View File

@@ -564,6 +564,48 @@ define void @test_build_vector_i16(ptr %ret_ptr, i16 %a, i16 %b) {
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>)

View File

@@ -738,6 +738,61 @@ define void @test_build_vector_i32(ptr %ret_ptr, i32 %a, i32 %b) {
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>)