diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 2a321e92eabb5..be53f51afe79f 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -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); diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td index de278aa51d19b..599358368594f 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td @@ -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; def : StPat; diff --git a/llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll b/llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll index 79cf5b7903454..acbb2401fd92e 100644 --- a/llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll +++ b/llvm/test/CodeGen/RISCV/rvp-ext-rv32.ll @@ -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>) diff --git a/llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll b/llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll index 36996f0ac7ac8..f05c60c9146a5 100644 --- a/llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll +++ b/llvm/test/CodeGen/RISCV/rvp-ext-rv64.ll @@ -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>)