diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index ab2652eac3823..899871edc9f7b 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -21872,6 +21872,44 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N, return N->getOperand(0); break; } + case RISCVISD::VMERGE_VL: { + // vmerge_vl allones, x, y, passthru, vl -> vmv_v_v passthru, x, vl + SDValue Mask = N->getOperand(0); + SDValue True = N->getOperand(1); + SDValue Passthru = N->getOperand(3); + SDValue VL = N->getOperand(4); + + // Fixed vectors are wrapped in scalable containers, unwrap them. + using namespace SDPatternMatch; + SDValue SubVec; + if (sd_match(Mask, m_InsertSubvector(m_Undef(), m_Value(SubVec), m_Zero()))) + Mask = SubVec; + + if (!isOneOrOneSplat(Mask)) + break; + + return DAG.getNode(RISCVISD::VMV_V_V_VL, SDLoc(N), N->getSimpleValueType(0), + Passthru, True, VL); + } + case RISCVISD::VMV_V_V_VL: { + // vmv_v_v passthru, splat(x), vl -> vmv_v_x passthru, x, vl + SDValue Passthru = N->getOperand(0); + SDValue Src = N->getOperand(1); + SDValue VL = N->getOperand(2); + + // Fixed vectors are wrapped in scalable containers, unwrap them. + using namespace SDPatternMatch; + SDValue SubVec; + if (sd_match(Src, m_InsertSubvector(m_Undef(), m_Value(SubVec), m_Zero()))) + Src = SubVec; + + SDValue SplatVal = DAG.getSplatValue(Src); + if (!SplatVal) + break; + MVT VT = N->getSimpleValueType(0); + return lowerScalarSplat(Passthru, SplatVal, VL, VT, SDLoc(N), DAG, + Subtarget); + } case RISCVISD::VSLIDEDOWN_VL: case RISCVISD::VSLIDEUP_VL: if (N->getOperand(1)->isUndef()) diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vpmerge.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vpmerge.ll index 7968c5190eb01..0bacb5c26cb4a 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vpmerge.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-vpmerge.ll @@ -1353,3 +1353,48 @@ define <32 x double> @vpmerge_vf_v32f64(double %a, <32 x double> %vb, <32 x i1> %v = call <32 x double> @llvm.vp.merge.v32f64(<32 x i1> %m, <32 x double> %va, <32 x double> %vb, i32 %evl) ret <32 x double> %v } + +define <4 x i32> @splat_v4i32(i32 %x, i32 zeroext %evl) { +; CHECK-LABEL: splat_v4i32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli zero, a1, e32, m1, ta, ma +; CHECK-NEXT: vmv.v.x v8, a0 +; CHECK-NEXT: ret + %head = insertelement <4 x i32> poison, i32 %x, i32 0 + %splat = shufflevector <4 x i32> %head, <4 x i32> poison, <4 x i32> zeroinitializer + %v = call <4 x i32> @llvm.vp.merge(<4 x i1> splat (i1 true), <4 x i32> %splat, <4 x i32> poison, i32 %evl) + ret <4 x i32> %v +} + +define <4 x float> @splat_v4f32(float %x, i32 zeroext %evl) { +; CHECK-LABEL: splat_v4f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli zero, a0, e32, m1, ta, ma +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: ret + %head = insertelement <4 x float> poison, float %x, i32 0 + %splat = shufflevector <4 x float> %head, <4 x float> poison, <4 x i32> zeroinitializer + %v = call <4 x float> @llvm.vp.merge(<4 x i1> splat (i1 true), <4 x float> %splat, <4 x float> poison, i32 %evl) + ret <4 x float> %v +} + +define <4 x i32> @splat_v4i32_const(i32 zeroext %evl) { +; CHECK-LABEL: splat_v4i32_const: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli zero, a0, e32, m1, ta, ma +; CHECK-NEXT: vmv.v.i v8, 1 +; CHECK-NEXT: ret + %v = call <4 x i32> @llvm.vp.merge(<4 x i1> splat (i1 true), <4 x i32> splat (i32 1), <4 x i32> poison, i32 %evl) + ret <4 x i32> %v +} + +define <4 x float> @splat_v4f32_const(i32 zeroext %evl) { +; CHECK-LABEL: splat_v4f32_const: +; CHECK: # %bb.0: +; CHECK-NEXT: lui a1, 270976 +; CHECK-NEXT: vsetvli zero, a0, e32, m1, ta, ma +; CHECK-NEXT: vmv.v.x v8, a1 +; CHECK-NEXT: ret + %v = call <4 x float> @llvm.vp.merge(<4 x i1> splat (i1 true), <4 x float> splat (float 42.0), <4 x float> poison, i32 %evl) + ret <4 x float> %v +} diff --git a/llvm/test/CodeGen/RISCV/rvv/vpmerge-sdnode.ll b/llvm/test/CodeGen/RISCV/rvv/vpmerge-sdnode.ll index 03697aafea45d..f92ee37051840 100644 --- a/llvm/test/CodeGen/RISCV/rvv/vpmerge-sdnode.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vpmerge-sdnode.ll @@ -1663,3 +1663,48 @@ define @vpmerge_vf_nxv8f64(double %a, @llvm.vp.merge.nxv8f64( %m, %va, %vb, i32 %evl) ret %v } + +define @splat_nxv2i32(i32 %x, i32 zeroext %evl) { +; CHECK-LABEL: splat_nxv2i32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli zero, a1, e32, m1, ta, ma +; CHECK-NEXT: vmv.v.x v8, a0 +; CHECK-NEXT: ret + %head = insertelement poison, i32 %x, i32 0 + %splat = shufflevector %head, poison, zeroinitializer + %v = call @llvm.vp.merge( splat (i1 true), %splat, poison, i32 %evl) + ret %v +} + +define @splat_nxv2f32(float %x, i32 zeroext %evl) { +; CHECK-LABEL: splat_nxv2f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli zero, a0, e32, m1, ta, ma +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: ret + %head = insertelement poison, float %x, i32 0 + %splat = shufflevector %head, poison, zeroinitializer + %v = call @llvm.vp.merge( splat (i1 true), %splat, poison, i32 %evl) + ret %v +} + +define @splat_nxv2i32_const(i32 zeroext %evl) { +; CHECK-LABEL: splat_nxv2i32_const: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli zero, a0, e32, m1, ta, ma +; CHECK-NEXT: vmv.v.i v8, 1 +; CHECK-NEXT: ret + %v = call @llvm.vp.merge( splat (i1 true), splat (i32 1), poison, i32 %evl) + ret %v +} + +define @splat_nxv2f32_const(i32 zeroext %evl) { +; CHECK-LABEL: splat_nxv2f32_const: +; CHECK: # %bb.0: +; CHECK-NEXT: lui a1, 270976 +; CHECK-NEXT: vsetvli zero, a0, e32, m1, ta, ma +; CHECK-NEXT: vmv.v.x v8, a1 +; CHECK-NEXT: ret + %v = call @llvm.vp.merge( splat (i1 true), splat (float 42.0), poison, i32 %evl) + ret %v +}