diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 17d7db95886a..228c28fa6333 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -578,7 +578,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM, if (VT != MVT::v2i32) setOperationAction({ISD::ABS, ISD::ABDS, ISD::ABDU}, VT, Legal); if (VT.getVectorElementType() != MVT::i8) - setOperationAction(ISD::SSHLSAT, VT, Legal); + setOperationAction(ISD::SSHLSAT, VT, Custom); } setOperationAction(ISD::SPLAT_VECTOR, VTs, Legal); setOperationAction(ISD::BUILD_VECTOR, VTs, Legal); @@ -8891,6 +8891,20 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op, assert(Op.getOperand(1).getValueType() == MVT::i32 && Subtarget.is64Bit() && "Unexpected custom legalisation"); return SDValue(); + case ISD::SSHLSAT: { + MVT VT = Op.getSimpleValueType(); + assert(VT.isFixedLengthVector() && Subtarget.hasStdExtP() && + "Unexptect custom legalisation"); + APInt Splat; + if (!ISD::isConstantSplatVector(Op.getOperand(1).getNode(), Splat)) + return SDValue(); + uint64_t ShAmt = Splat.getZExtValue(); + if (ShAmt >= VT.getVectorElementType().getSizeInBits()) + return SDValue(); + SDLoc DL(Op); + return DAG.getNode(RISCVISD::PSSLAI, DL, VT, Op.getOperand(0), + DAG.getTargetConstant(ShAmt, DL, Subtarget.getXLenVT())); + } case ISD::FABS: case ISD::FNEG: if (Op.getValueType() == MVT::f16 || Op.getValueType() == MVT::bf16) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td index c0e392ca04b0..9c08ae89430c 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td @@ -1664,6 +1664,7 @@ def STD_RISCVPackedShift : SDTypeProfile<1, 2, [SDTCisVec<0>, def riscv_pshl : RVSDNode<"PSHL", STD_RISCVPackedShift>; def riscv_psrl : RVSDNode<"PSRL", STD_RISCVPackedShift>; def riscv_psra : RVSDNode<"PSRA", STD_RISCVPackedShift>; +def riscv_psslai : RVSDNode<"PSSLAI", STD_RISCVPackedShift>; // Bitwise merge: res = (~op0 & op1) | (op0 & op2) def SDT_RISCVMERGE : SDTypeProfile<1, 3, [SDTCisInt<0>, @@ -1795,8 +1796,8 @@ let Predicates = [HasStdExtP] in { (PSRAI_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)>; + def: Pat<(XLenVecI16VT (riscv_psslai GPR:$rs1, timm:$shamt)), + (PSSLAI_H GPR:$rs1, timm:$shamt)>; // 8-bit logical shift left/right def: Pat<(XLenVecI8VT (riscv_pshl GPR:$rs1, GPR:$rs2)), @@ -1979,8 +1980,8 @@ let Predicates = [HasStdExtP, IsRV64] in { (PSRAI_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)>; + def: Pat<(v2i32 (riscv_psslai GPR:$rs1, timm:$shamt)), + (PSSLAI_W GPR:$rs1, timm:$shamt)>; // 32-bit logical shift left/right def: Pat<(v2i32 (riscv_pshl GPR:$rs1, GPR:$rs2)), diff --git a/llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll b/llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll index 49b06b5ca559..4aaf3d3aa420 100644 --- a/llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll +++ b/llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll @@ -680,7 +680,7 @@ define <4 x i8> @test_pslli_b(<4 x i8> %a) { ret <4 x i8> %res } -; Test arithmetic saturation shift left immediate for v2i16 +; Test saturating shift left arithmetic with splat immediate shift amount for v2i16 define <2 x i16> @test_psslai_h(<2 x i16> %a) { ; CHECK-LABEL: test_psslai_h: ; CHECK: # %bb.0: @@ -690,7 +690,7 @@ define <2 x i16> @test_psslai_h(<2 x i16> %a) { ret <2 x i16> %res } -; Test arithmetic saturation shift left immediate for v4i8 +; Test saturating shift left arithmetic with splat immediate shift amount for v4i8 define <4 x i8> @test_psslai_b(<4 x i8> %a) { ; CHECK-LABEL: test_psslai_b: ; CHECK: # %bb.0: @@ -707,6 +707,90 @@ define <4 x i8> @test_psslai_b(<4 x i8> %a) { ret <4 x i8> %res } +; Test saturating shift left arithmetic with splat shift amount for v2i16 +define <2 x i16> @test_pssla_hs(<2 x i16> %a, i16 %shamt) { +; CHECK-LABEL: test_pssla_hs: +; CHECK: # %bb.0: +; CHECK-NEXT: pmslt.h a2, a0, zero +; CHECK-NEXT: lui a3, 8 +; CHECK-NEXT: plui.h a4, -512 +; CHECK-NEXT: addi a3, a3, -1 +; CHECK-NEXT: padd.hs a3, zero, a3 +; CHECK-NEXT: merge a2, a3, a4 +; CHECK-NEXT: psll.hs a3, a0, a1 +; CHECK-NEXT: psra.hs a1, a3, a1 +; CHECK-NEXT: pmseq.h a0, a0, a1 +; CHECK-NEXT: merge a0, a2, a3 +; CHECK-NEXT: ret + %insert = insertelement <2 x i16> poison, i16 %shamt, i32 0 + %b = shufflevector <2 x i16> %insert, <2 x i16> poison, <2 x i32> zeroinitializer + %res = call <2 x i16> @llvm.sshl.sat.v2i16(<2 x i16> %a, <2 x i16> %b) + ret <2 x i16> %res +} + +; Test saturating shift left arithmetic with non-splat shift amount for v2i16 +define <2 x i16> @test_pssla_h(<2 x i16> %a, <2 x i16> %b) { +; CHECK-RV32-LABEL: test_pssla_h: +; CHECK-RV32: # %bb.0: +; CHECK-RV32-NEXT: sll a2, a0, a1 +; CHECK-RV32-NEXT: srli a3, a1, 16 +; CHECK-RV32-NEXT: srli a4, a0, 16 +; CHECK-RV32-NEXT: sext.h a5, a2 +; CHECK-RV32-NEXT: sra a1, a5, a1 +; CHECK-RV32-NEXT: pmslt.h a5, a0, zero +; CHECK-RV32-NEXT: sll a4, a4, a3 +; CHECK-RV32-NEXT: pack a2, a2, a4 +; CHECK-RV32-NEXT: sext.h a4, a4 +; CHECK-RV32-NEXT: sra a3, a4, a3 +; CHECK-RV32-NEXT: lui a4, 8 +; CHECK-RV32-NEXT: pack a1, a1, a3 +; CHECK-RV32-NEXT: plui.h a3, -512 +; CHECK-RV32-NEXT: addi a4, a4, -1 +; CHECK-RV32-NEXT: padd.hs a4, zero, a4 +; CHECK-RV32-NEXT: pmseq.h a0, a0, a1 +; CHECK-RV32-NEXT: merge a5, a4, a3 +; CHECK-RV32-NEXT: merge a0, a5, a2 +; CHECK-RV32-NEXT: ret +; +; CHECK-RV64-LABEL: test_pssla_h: +; CHECK-RV64: # %bb.0: +; CHECK-RV64-NEXT: srli a2, a1, 48 +; CHECK-RV64-NEXT: srli a3, a0, 48 +; CHECK-RV64-NEXT: srli a4, a1, 32 +; CHECK-RV64-NEXT: srli a5, a0, 32 +; CHECK-RV64-NEXT: sll a6, a0, a1 +; CHECK-RV64-NEXT: srli a7, a1, 16 +; CHECK-RV64-NEXT: srli t0, a0, 16 +; CHECK-RV64-NEXT: pmslt.h t1, a0, zero +; CHECK-RV64-NEXT: sll a3, a3, a2 +; CHECK-RV64-NEXT: sll a5, a5, a4 +; CHECK-RV64-NEXT: sll t0, t0, a7 +; CHECK-RV64-NEXT: sext.h t2, a6 +; CHECK-RV64-NEXT: sra a1, t2, a1 +; CHECK-RV64-NEXT: ppaire.h t2, a5, a3 +; CHECK-RV64-NEXT: ppaire.h a6, a6, t0 +; CHECK-RV64-NEXT: pack a6, a6, t2 +; CHECK-RV64-NEXT: lui t2, 8 +; CHECK-RV64-NEXT: sext.h a3, a3 +; CHECK-RV64-NEXT: sra a2, a3, a2 +; CHECK-RV64-NEXT: plui.h a3, -512 +; CHECK-RV64-NEXT: addi t2, t2, -1 +; CHECK-RV64-NEXT: sext.h a5, a5 +; CHECK-RV64-NEXT: sext.h t0, t0 +; CHECK-RV64-NEXT: padd.hs t2, zero, t2 +; CHECK-RV64-NEXT: sra a4, a5, a4 +; CHECK-RV64-NEXT: sra a5, t0, a7 +; CHECK-RV64-NEXT: ppaire.h a2, a4, a2 +; CHECK-RV64-NEXT: ppaire.h a1, a1, a5 +; CHECK-RV64-NEXT: pack a1, a1, a2 +; CHECK-RV64-NEXT: pmseq.h a0, a0, a1 +; CHECK-RV64-NEXT: merge t1, t2, a3 +; CHECK-RV64-NEXT: merge a0, t1, a6 +; CHECK-RV64-NEXT: ret + %res = call <2 x i16> @llvm.sshl.sat.v2i16(<2 x i16> %a, <2 x i16> %b) + ret <2 x i16> %res +} + ; Test logical shift right immediate define <2 x i16> @test_psrli_h(<2 x i16> %a) { ; CHECK-LABEL: test_psrli_h: @@ -1762,10 +1846,10 @@ define <2 x i16> @test_select_v2i16(i1 %cond, <2 x i16> %a, <2 x i16> %b) { ; CHECK: # %bb.0: ; CHECK-NEXT: andi a3, a0, 1 ; CHECK-NEXT: mv a0, a1 -; CHECK-NEXT: bnez a3, .LBB126_2 +; CHECK-NEXT: bnez a3, .LBB128_2 ; CHECK-NEXT: # %bb.1: ; CHECK-NEXT: mv a0, a2 -; CHECK-NEXT: .LBB126_2: +; CHECK-NEXT: .LBB128_2: ; CHECK-NEXT: ret %res = select i1 %cond, <2 x i16> %a, <2 x i16> %b ret <2 x i16> %res @@ -1776,10 +1860,10 @@ define <4 x i8> @test_select_v4i8(i1 %cond, <4 x i8> %a, <4 x i8> %b) { ; CHECK: # %bb.0: ; CHECK-NEXT: andi a3, a0, 1 ; CHECK-NEXT: mv a0, a1 -; CHECK-NEXT: bnez a3, .LBB127_2 +; CHECK-NEXT: bnez a3, .LBB129_2 ; CHECK-NEXT: # %bb.1: ; CHECK-NEXT: mv a0, a2 -; CHECK-NEXT: .LBB127_2: +; CHECK-NEXT: .LBB129_2: ; CHECK-NEXT: ret %res = select i1 %cond, <4 x i8> %a, <4 x i8> %b ret <4 x i8> %res diff --git a/llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll b/llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll index e7a11506da22..1063ae9e020e 100644 --- a/llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll +++ b/llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll @@ -995,7 +995,7 @@ define <8 x i8> @test_psrai_b(<8 x i8> %a) { ret <8 x i8> %res } -; Test arithmetic saturation shift left immediate for v2i32 +; Test saturating shift left arithmetic with splat immediate shift amount for v2i32 define <2 x i32> @test_psslai_w(<2 x i32> %a) { ; CHECK-LABEL: test_psslai_w: ; CHECK: # %bb.0: @@ -1005,7 +1005,7 @@ define <2 x i32> @test_psslai_w(<2 x i32> %a) { ret <2 x i32> %res } -; Test arithmetic saturation shift left immediate for v4i16 +; Test saturating shift left arithmetic with splat immediate shift amount for v4i16 define <4 x i16> @test_psslai_h(<4 x i16> %a) { ; CHECK-LABEL: test_psslai_h: ; CHECK: # %bb.0: @@ -1015,7 +1015,7 @@ define <4 x i16> @test_psslai_h(<4 x i16> %a) { ret <4 x i16> %res } -; Test arithmetic saturation shift left immediate for v8i8 +; Test saturating shift left arithmetic with splat immediate shift amount for v8i8 define <8 x i8> @test_psslai_b(<8 x i8> %a) { ; CHECK-LABEL: test_psslai_b: ; CHECK: # %bb.0: @@ -1032,6 +1032,114 @@ define <8 x i8> @test_psslai_b(<8 x i8> %a) { ret <8 x i8> %res } +; Test saturating shift left arithmetic with splat shift amount for v4i16 +define <4 x i16> @test_pssla_hs(<4 x i16> %a, i16 %shamt) { +; CHECK-LABEL: test_pssla_hs: +; CHECK: # %bb.0: +; CHECK-NEXT: pmslt.h a2, a0, zero +; CHECK-NEXT: lui a3, 8 +; CHECK-NEXT: plui.h a4, -512 +; CHECK-NEXT: addi a3, a3, -1 +; CHECK-NEXT: padd.hs a3, zero, a3 +; CHECK-NEXT: merge a2, a3, a4 +; CHECK-NEXT: psll.hs a3, a0, a1 +; CHECK-NEXT: psra.hs a1, a3, a1 +; CHECK-NEXT: pmseq.h a0, a0, a1 +; CHECK-NEXT: merge a0, a2, a3 +; CHECK-NEXT: ret + %insert = insertelement <4 x i16> poison, i16 %shamt, i32 0 + %b = shufflevector <4 x i16> %insert, <4 x i16> poison, <4 x i32> zeroinitializer + %res = call <4 x i16> @llvm.sshl.sat.v4i16(<4 x i16> %a, <4 x i16> %b) + ret <4 x i16> %res +} + +; Test saturating shift left arithmetic with splat shift amount for v2i32 +define <2 x i32> @test_pssla_ws(<2 x i32> %a, i32 %shamt) { +; CHECK-LABEL: test_pssla_ws: +; CHECK: # %bb.0: +; CHECK-NEXT: pmslt.w a2, a0, zero +; CHECK-NEXT: lui a3, 524288 +; CHECK-NEXT: plui.w a4, -512 +; CHECK-NEXT: addiw a3, a3, -1 +; CHECK-NEXT: padd.ws a3, zero, a3 +; CHECK-NEXT: merge a2, a3, a4 +; CHECK-NEXT: psll.ws a3, a0, a1 +; CHECK-NEXT: psra.ws a1, a3, a1 +; CHECK-NEXT: pmseq.w a0, a0, a1 +; CHECK-NEXT: merge a0, a2, a3 +; CHECK-NEXT: ret + %insert = insertelement <2 x i32> poison, i32 %shamt, i32 0 + %b = shufflevector <2 x i32> %insert, <2 x i32> poison, <2 x i32> zeroinitializer + %res = call <2 x i32> @llvm.sshl.sat.v2i32(<2 x i32> %a, <2 x i32> %b) + ret <2 x i32> %res +} + +; Test saturating shift left arithmetic with non-splat shift amount for v4i16 +define <4 x i16> @test_pssla_h(<4 x i16> %a, <4 x i16> %b) { +; CHECK-LABEL: test_pssla_h: +; CHECK: # %bb.0: +; CHECK-NEXT: srli a2, a1, 48 +; CHECK-NEXT: srli a3, a0, 48 +; CHECK-NEXT: srli a4, a1, 32 +; CHECK-NEXT: srli a5, a0, 32 +; CHECK-NEXT: sll a6, a0, a1 +; CHECK-NEXT: srli a7, a1, 16 +; CHECK-NEXT: srli t0, a0, 16 +; CHECK-NEXT: pmslt.h t1, a0, zero +; CHECK-NEXT: sll a3, a3, a2 +; CHECK-NEXT: sll a5, a5, a4 +; CHECK-NEXT: sll t0, t0, a7 +; CHECK-NEXT: sext.h t2, a6 +; CHECK-NEXT: sra a1, t2, a1 +; CHECK-NEXT: ppaire.h t2, a5, a3 +; CHECK-NEXT: ppaire.h a6, a6, t0 +; CHECK-NEXT: pack a6, a6, t2 +; CHECK-NEXT: lui t2, 8 +; CHECK-NEXT: sext.h a3, a3 +; CHECK-NEXT: sra a2, a3, a2 +; CHECK-NEXT: plui.h a3, -512 +; CHECK-NEXT: addi t2, t2, -1 +; CHECK-NEXT: sext.h a5, a5 +; CHECK-NEXT: sext.h t0, t0 +; CHECK-NEXT: padd.hs t2, zero, t2 +; CHECK-NEXT: sra a4, a5, a4 +; CHECK-NEXT: sra a5, t0, a7 +; CHECK-NEXT: ppaire.h a2, a4, a2 +; CHECK-NEXT: ppaire.h a1, a1, a5 +; CHECK-NEXT: pack a1, a1, a2 +; CHECK-NEXT: pmseq.h a0, a0, a1 +; CHECK-NEXT: merge t1, t2, a3 +; CHECK-NEXT: merge a0, t1, a6 +; CHECK-NEXT: ret + %res = call <4 x i16> @llvm.sshl.sat.v4i16(<4 x i16> %a, <4 x i16> %b) + ret <4 x i16> %res +} + +; Test saturating shift left arithmetic with non-splat shift amount for v2i32 +define <2 x i32> @test_pssla_w(<2 x i32> %a, <2 x i32> %b) { +; CHECK-LABEL: test_pssla_w: +; CHECK: # %bb.0: +; CHECK-NEXT: sllw a2, a0, a1 +; CHECK-NEXT: srli a3, a1, 32 +; CHECK-NEXT: srli a4, a0, 32 +; CHECK-NEXT: pmslt.w a5, a0, zero +; CHECK-NEXT: sllw a4, a4, a3 +; CHECK-NEXT: sraw a1, a2, a1 +; CHECK-NEXT: pack a2, a2, a4 +; CHECK-NEXT: sraw a3, a4, a3 +; CHECK-NEXT: lui a4, 524288 +; CHECK-NEXT: pack a1, a1, a3 +; CHECK-NEXT: plui.w a3, -512 +; CHECK-NEXT: addiw a4, a4, -1 +; CHECK-NEXT: padd.ws a4, zero, a4 +; CHECK-NEXT: pmseq.w a0, a0, a1 +; CHECK-NEXT: merge a5, a4, a3 +; CHECK-NEXT: merge a0, a5, a2 +; CHECK-NEXT: ret + %res = call <2 x i32> @llvm.sshl.sat.v2i32(<2 x i32> %a, <2 x i32> %b) + ret <2 x i32> %res +} + ; Test logical shift left(scalar shamt) define <2 x i32> @test_psll_ws(<2 x i32> %a, i32 %shamt) { ; CHECK-LABEL: test_psll_ws: @@ -2158,10 +2266,10 @@ define <4 x i16> @test_select_v4i16(i1 %cond, <4 x i16> %a, <4 x i16> %b) { ; CHECK: # %bb.0: ; CHECK-NEXT: andi a3, a0, 1 ; CHECK-NEXT: mv a0, a1 -; CHECK-NEXT: bnez a3, .LBB177_2 +; CHECK-NEXT: bnez a3, .LBB181_2 ; CHECK-NEXT: # %bb.1: ; CHECK-NEXT: mv a0, a2 -; CHECK-NEXT: .LBB177_2: +; CHECK-NEXT: .LBB181_2: ; CHECK-NEXT: ret %res = select i1 %cond, <4 x i16> %a, <4 x i16> %b ret <4 x i16> %res @@ -2172,10 +2280,10 @@ define <8 x i8> @test_select_v8i8(i1 %cond, <8 x i8> %a, <8 x i8> %b) { ; CHECK: # %bb.0: ; CHECK-NEXT: andi a3, a0, 1 ; CHECK-NEXT: mv a0, a1 -; CHECK-NEXT: bnez a3, .LBB178_2 +; CHECK-NEXT: bnez a3, .LBB182_2 ; CHECK-NEXT: # %bb.1: ; CHECK-NEXT: mv a0, a2 -; CHECK-NEXT: .LBB178_2: +; CHECK-NEXT: .LBB182_2: ; CHECK-NEXT: ret %res = select i1 %cond, <8 x i8> %a, <8 x i8> %b ret <8 x i8> %res @@ -2186,10 +2294,10 @@ define <2 x i32> @test_select_v2i32(i1 %cond, <2 x i32> %a, <2 x i32> %b) { ; CHECK: # %bb.0: ; CHECK-NEXT: andi a3, a0, 1 ; CHECK-NEXT: mv a0, a1 -; CHECK-NEXT: bnez a3, .LBB179_2 +; CHECK-NEXT: bnez a3, .LBB183_2 ; CHECK-NEXT: # %bb.1: ; CHECK-NEXT: mv a0, a2 -; CHECK-NEXT: .LBB179_2: +; CHECK-NEXT: .LBB183_2: ; CHECK-NEXT: ret %res = select i1 %cond, <2 x i32> %a, <2 x i32> %b ret <2 x i32> %res