Skip to content

Commit d889b97

Browse files
authored
[RISCV][llvm] Support BUILD_VECTOR codegen for P extension (#169083)
1 parent 5d38cdd commit d889b97

File tree

5 files changed

+197
-1
lines changed

5 files changed

+197
-1
lines changed

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1867,6 +1867,43 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
18671867
CurDAG->RemoveDeadNode(Node);
18681868
return;
18691869
}
1870+
case RISCVISD::PPACK_DH: {
1871+
assert(Subtarget->enablePExtCodeGen() && Subtarget->isRV32());
1872+
1873+
SDValue Val0 = Node->getOperand(0);
1874+
SDValue Val1 = Node->getOperand(1);
1875+
SDValue Val2 = Node->getOperand(2);
1876+
SDValue Val3 = Node->getOperand(3);
1877+
1878+
SDValue Ops[] = {
1879+
CurDAG->getTargetConstant(RISCV::GPRPairRegClassID, DL, MVT::i32), Val0,
1880+
CurDAG->getTargetConstant(RISCV::sub_gpr_even, DL, MVT::i32), Val2,
1881+
CurDAG->getTargetConstant(RISCV::sub_gpr_odd, DL, MVT::i32)};
1882+
SDValue RegPair0 =
1883+
SDValue(CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL,
1884+
MVT::Untyped, Ops),
1885+
0);
1886+
SDValue Ops1[] = {
1887+
CurDAG->getTargetConstant(RISCV::GPRPairRegClassID, DL, MVT::i32), Val1,
1888+
CurDAG->getTargetConstant(RISCV::sub_gpr_even, DL, MVT::i32), Val3,
1889+
CurDAG->getTargetConstant(RISCV::sub_gpr_odd, DL, MVT::i32)};
1890+
SDValue RegPair1 =
1891+
SDValue(CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL,
1892+
MVT::Untyped, Ops1),
1893+
0);
1894+
1895+
MachineSDNode *PackDH = CurDAG->getMachineNode(
1896+
RISCV::PPACK_DH, DL, MVT::Untyped, {RegPair0, RegPair1});
1897+
1898+
SDValue Lo = CurDAG->getTargetExtractSubreg(RISCV::sub_gpr_even, DL,
1899+
MVT::i32, SDValue(PackDH, 0));
1900+
SDValue Hi = CurDAG->getTargetExtractSubreg(RISCV::sub_gpr_odd, DL,
1901+
MVT::i32, SDValue(PackDH, 0));
1902+
ReplaceUses(SDValue(Node, 0), Lo);
1903+
ReplaceUses(SDValue(Node, 1), Hi);
1904+
CurDAG->RemoveDeadNode(Node);
1905+
return;
1906+
}
18701907
case ISD::INTRINSIC_WO_CHAIN: {
18711908
unsigned IntNo = Node->getConstantOperandVal(0);
18721909
switch (IntNo) {
@@ -2696,7 +2733,8 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
26962733
case ISD::SCALAR_TO_VECTOR:
26972734
if (Subtarget->enablePExtCodeGen()) {
26982735
MVT SrcVT = Node->getOperand(0).getSimpleValueType();
2699-
if (VT == MVT::v2i32 && SrcVT == MVT::i64) {
2736+
if ((VT == MVT::v2i32 && SrcVT == MVT::i64) ||
2737+
(VT == MVT::v4i8 && SrcVT == MVT::i32)) {
27002738
ReplaceUses(SDValue(Node, 0), Node->getOperand(0));
27012739
CurDAG->RemoveDeadNode(Node);
27022740
return;

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
519519
setTruncStoreAction(MVT::v4i16, MVT::v4i8, Expand);
520520
} else {
521521
VTs.append({MVT::v2i16, MVT::v4i8});
522+
setOperationAction(ISD::BUILD_VECTOR, MVT::v4i8, Custom);
522523
}
523524
setOperationAction(ISD::UADDSAT, VTs, Legal);
524525
setOperationAction(ISD::SADDSAT, VTs, Legal);
@@ -4434,6 +4435,33 @@ static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG,
44344435

44354436
SDLoc DL(Op);
44364437

4438+
if (Subtarget.isRV32() && Subtarget.enablePExtCodeGen()) {
4439+
if (VT != MVT::v4i8)
4440+
return SDValue();
4441+
4442+
// <4 x i8> BUILD_VECTOR a, b, c, d -> PACK(PPACK.DH pair(a, b), pair(c, d))
4443+
SDValue Val0 =
4444+
DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4i8, Op->getOperand(0));
4445+
SDValue Val1 =
4446+
DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4i8, Op->getOperand(1));
4447+
SDValue Val2 =
4448+
DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4i8, Op->getOperand(2));
4449+
SDValue Val3 =
4450+
DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, MVT::v4i8, Op->getOperand(3));
4451+
SDValue PackDH =
4452+
DAG.getNode(RISCVISD::PPACK_DH, DL, {MVT::v2i16, MVT::v2i16},
4453+
{Val0, Val1, Val2, Val3});
4454+
4455+
return DAG.getNode(
4456+
ISD::BITCAST, DL, MVT::v4i8,
4457+
SDValue(
4458+
DAG.getMachineNode(
4459+
RISCV::PACK, DL, MVT::i32,
4460+
{DAG.getNode(ISD::BITCAST, DL, MVT::i32, PackDH.getValue(0)),
4461+
DAG.getNode(ISD::BITCAST, DL, MVT::i32, PackDH.getValue(1))}),
4462+
0));
4463+
}
4464+
44374465
// Proper support for f16 requires Zvfh. bf16 always requires special
44384466
// handling. We need to cast the scalar to integer and create an integer
44394467
// build_vector.

llvm/lib/Target/RISCV/RISCVInstrInfoP.td

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ def SImm8UnsignedAsmOperand : SImmAsmOperand<8, "Unsigned"> {
2424
let RenderMethod = "addSImm8UnsignedOperands";
2525
}
2626

27+
// (<2 x i16>, <2 x i16>) PPACK_DH (<4 x i8>, <4 x i8>, <4 x i8>, <4 x i8>)
28+
def SDT_RISCVPPackDH
29+
: SDTypeProfile<2, 4, [SDTCisVT<0, v2i16>, SDTCisSameAs<0, 1>,
30+
SDTCisVT<2, v4i8>, SDTCisSameAs<0, 3>,
31+
SDTCisSameAs<0, 4>, SDTCisSameAs<0, 5>]>;
32+
def riscv_ppack_dh : RVSDNode<"PPACK_DH", SDT_RISCVPPackDH>;
33+
2734
// A 8-bit signed immediate allowing range [-128, 255]
2835
// but represented as [-128, 127].
2936
def simm8_unsigned : RISCVOp, ImmLeaf<XLenVT, "return isInt<8>(Imm);"> {
@@ -1530,6 +1537,10 @@ let Predicates = [HasStdExtP, IsRV32] in {
15301537
def : StPat<store, SW, GPR, v2i16>;
15311538
def : LdPat<load, LW, v4i8>;
15321539
def : LdPat<load, LW, v2i16>;
1540+
1541+
// Build vector patterns
1542+
def : Pat<(v2i16 (build_vector (XLenVT GPR:$a), (XLenVT GPR:$b))),
1543+
(PACK GPR:$a, GPR:$b)>;
15331544
} // Predicates = [HasStdExtP, IsRV32]
15341545

15351546
let Predicates = [HasStdExtP, IsRV64] in {
@@ -1566,4 +1577,29 @@ let Predicates = [HasStdExtP, IsRV64] in {
15661577
def : LdPat<load, LD, v8i8>;
15671578
def : LdPat<load, LD, v4i16>;
15681579
def : LdPat<load, LD, v2i32>;
1580+
1581+
// Build vector patterns
1582+
def : Pat<(v8i8 (build_vector (XLenVT GPR:$a), (XLenVT GPR:$b),
1583+
(XLenVT GPR:$c), (XLenVT GPR:$d),
1584+
(XLenVT undef), (XLenVT undef),
1585+
(XLenVT undef), (XLenVT undef))),
1586+
(PPACK_W (PPACK_H GPR:$a, GPR:$b), (PPACK_H GPR:$c, GPR:$d))>;
1587+
1588+
def : Pat<(v8i8 (build_vector (XLenVT GPR:$a), (XLenVT GPR:$b),
1589+
(XLenVT GPR:$c), (XLenVT GPR:$d),
1590+
(XLenVT GPR:$e), (XLenVT GPR:$f),
1591+
(XLenVT GPR:$g), (XLenVT GPR:$h))),
1592+
(PACK(PPACK_W (PPACK_H GPR:$a, GPR:$b), (PPACK_H GPR:$c, GPR:$d)),
1593+
(PPACK_W (PPACK_H GPR:$e, GPR:$f), (PPACK_H GPR:$g, GPR:$h)))>;
1594+
1595+
def : Pat<(v4i16 (build_vector (XLenVT GPR:$a), (XLenVT GPR:$b),
1596+
(XLenVT undef), (XLenVT undef))),
1597+
(PPACK_W GPR:$a, GPR:$b)>;
1598+
1599+
def : Pat<(v4i16 (build_vector (XLenVT GPR:$a), (XLenVT GPR:$b),
1600+
(XLenVT GPR:$c), (XLenVT GPR:$d))),
1601+
(PACK (PPACK_W GPR:$a, GPR:$b), (PPACK_W GPR:$c, GPR:$d))>;
1602+
1603+
def : Pat<(v2i32 (build_vector (XLenVT GPR:$a), (XLenVT GPR:$b))),
1604+
(PACK GPR:$a, GPR:$b)>;
15691605
} // Predicates = [HasStdExtP, IsRV64]

llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,47 @@ define void @test_non_const_splat_i16(ptr %ret_ptr, ptr %a_ptr, i16 %elt) {
523523
ret void
524524
}
525525

526+
define void @test_build_vector_i8(i8 %a, i8 %c, i8 %b, i8 %d, ptr %ret_ptr) {
527+
; CHECK-RV32-LABEL: test_build_vector_i8:
528+
; CHECK-RV32: # %bb.0:
529+
; CHECK-RV32-NEXT: ppack.dh a0, a0, a2
530+
; CHECK-RV32-NEXT: pack a0, a0, a1
531+
; CHECK-RV32-NEXT: sw a0, 0(a4)
532+
; CHECK-RV32-NEXT: ret
533+
;
534+
; CHECK-RV64-LABEL: test_build_vector_i8:
535+
; CHECK-RV64: # %bb.0:
536+
; CHECK-RV64-NEXT: ppack.h a1, a1, a3
537+
; CHECK-RV64-NEXT: ppack.h a0, a0, a2
538+
; CHECK-RV64-NEXT: ppack.w a0, a0, a1
539+
; CHECK-RV64-NEXT: sw a0, 0(a4)
540+
; CHECK-RV64-NEXT: ret
541+
%v0 = insertelement <4 x i8> poison, i8 %a, i32 0
542+
%v1 = insertelement <4 x i8> %v0, i8 %b, i32 1
543+
%v2 = insertelement <4 x i8> %v1, i8 %c, i32 2
544+
%v3 = insertelement <4 x i8> %v2, i8 %d, i32 3
545+
store <4 x i8> %v3, ptr %ret_ptr
546+
ret void
547+
}
548+
549+
define void @test_build_vector_i16(ptr %ret_ptr, i16 %a, i16 %b) {
550+
; CHECK-RV32-LABEL: test_build_vector_i16:
551+
; CHECK-RV32: # %bb.0:
552+
; CHECK-RV32-NEXT: pack a1, a1, a2
553+
; CHECK-RV32-NEXT: sw a1, 0(a0)
554+
; CHECK-RV32-NEXT: ret
555+
;
556+
; CHECK-RV64-LABEL: test_build_vector_i16:
557+
; CHECK-RV64: # %bb.0:
558+
; CHECK-RV64-NEXT: ppack.w a1, a1, a2
559+
; CHECK-RV64-NEXT: sw a1, 0(a0)
560+
; CHECK-RV64-NEXT: ret
561+
%v0 = insertelement <2 x i16> poison, i16 %a, i32 0
562+
%v1 = insertelement <2 x i16> %v0, i16 %b, i32 1
563+
store <2 x i16> %v1, ptr %ret_ptr
564+
ret void
565+
}
566+
526567
; Intrinsic declarations
527568
declare <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16>, <2 x i16>)
528569
declare <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16>, <2 x i16>)

llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,59 @@ define void @test_non_const_splat_i32(ptr %ret_ptr, ptr %a_ptr, i32 %elt) {
685685
ret void
686686
}
687687

688+
define void @test_build_vector_i8(ptr %ret_ptr, i8 %a, i8 %b, i8 %c, i8 %d, i8 %e, i8 %f, i8 %g, i8 %h) {
689+
; CHECK-LABEL: test_build_vector_i8:
690+
; CHECK: # %bb.0:
691+
; CHECK-NEXT: lbu t0, 0(sp)
692+
; CHECK-NEXT: ppack.h a5, a5, a6
693+
; CHECK-NEXT: ppack.h a3, a3, a4
694+
; CHECK-NEXT: ppack.h a1, a1, a2
695+
; CHECK-NEXT: ppack.h a2, a7, t0
696+
; CHECK-NEXT: ppack.w a2, a5, a2
697+
; CHECK-NEXT: ppack.w a1, a1, a3
698+
; CHECK-NEXT: pack a1, a1, a2
699+
; CHECK-NEXT: sd a1, 0(a0)
700+
; CHECK-NEXT: ret
701+
%v0 = insertelement <8 x i8> poison, i8 %a, i32 0
702+
%v1 = insertelement <8 x i8> %v0, i8 %b, i32 1
703+
%v2 = insertelement <8 x i8> %v1, i8 %c, i32 2
704+
%v3 = insertelement <8 x i8> %v2, i8 %d, i32 3
705+
%v4 = insertelement <8 x i8> %v3, i8 %e, i32 4
706+
%v5 = insertelement <8 x i8> %v4, i8 %f, i32 5
707+
%v6 = insertelement <8 x i8> %v5, i8 %g, i32 6
708+
%v7 = insertelement <8 x i8> %v6, i8 %h, i32 7
709+
store <8 x i8> %v7, ptr %ret_ptr
710+
ret void
711+
}
712+
713+
define void @test_build_vector_i16(ptr %ret_ptr, i16 %a, i16 %b, i16 %c, i16 %d) {
714+
; CHECK-LABEL: test_build_vector_i16:
715+
; CHECK: # %bb.0:
716+
; CHECK-NEXT: ppack.w a3, a3, a4
717+
; CHECK-NEXT: ppack.w a1, a1, a2
718+
; CHECK-NEXT: pack a1, a1, a3
719+
; CHECK-NEXT: sd a1, 0(a0)
720+
; CHECK-NEXT: ret
721+
%v0 = insertelement <4 x i16> poison, i16 %a, i32 0
722+
%v1 = insertelement <4 x i16> %v0, i16 %b, i32 1
723+
%v2 = insertelement <4 x i16> %v1, i16 %c, i32 2
724+
%v3 = insertelement <4 x i16> %v2, i16 %d, i32 3
725+
store <4 x i16> %v3, ptr %ret_ptr
726+
ret void
727+
}
728+
729+
define void @test_build_vector_i32(ptr %ret_ptr, i32 %a, i32 %b) {
730+
; CHECK-LABEL: test_build_vector_i32:
731+
; CHECK: # %bb.0:
732+
; CHECK-NEXT: pack a1, a1, a2
733+
; CHECK-NEXT: sd a1, 0(a0)
734+
; CHECK-NEXT: ret
735+
%v0 = insertelement <2 x i32> poison, i32 %a, i32 0
736+
%v1 = insertelement <2 x i32> %v0, i32 %b, i32 1
737+
store <2 x i32> %v1, ptr %ret_ptr
738+
ret void
739+
}
740+
688741
; Intrinsic declarations
689742
declare <4 x i16> @llvm.sadd.sat.v4i16(<4 x i16>, <4 x i16>)
690743
declare <4 x i16> @llvm.uadd.sat.v4i16(<4 x i16>, <4 x i16>)

0 commit comments

Comments
 (0)