diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -1578,6 +1578,7 @@ case ISD::STRICT_UINT_TO_FP: Res = PromoteIntOp_STRICT_UINT_TO_FP(N); break; case ISD::ZERO_EXTEND: Res = PromoteIntOp_ZERO_EXTEND(N); break; case ISD::EXTRACT_SUBVECTOR: Res = PromoteIntOp_EXTRACT_SUBVECTOR(N); break; + case ISD::INSERT_SUBVECTOR: Res = PromoteIntOp_INSERT_SUBVECTOR(N); break; case ISD::SHL: case ISD::SRA: @@ -5078,6 +5079,21 @@ return DAG.getAnyExtOrTrunc(Ext, dl, N->getValueType(0)); } +SDValue DAGTypeLegalizer::PromoteIntOp_INSERT_SUBVECTOR(SDNode *N) { + SDLoc dl(N); + // The result type is equal to the first input operand's type, so the + // type that needs promoting must be the second source vector. + SDValue V0 = N->getOperand(0); + SDValue V1 = GetPromotedInteger(N->getOperand(1)); + SDValue Idx = N->getOperand(2); + EVT PromVT = EVT::getVectorVT(*DAG.getContext(), + V1.getValueType().getVectorElementType(), + V0.getValueType().getVectorElementCount()); + V0 = DAG.getAnyExtOrTrunc(V0, dl, PromVT); + SDValue Ext = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, PromVT, V0, V1, Idx); + return DAG.getAnyExtOrTrunc(Ext, dl, N->getValueType(0)); +} + SDValue DAGTypeLegalizer::PromoteIntOp_EXTRACT_SUBVECTOR(SDNode *N) { SDLoc dl(N); SDValue V0 = GetPromotedInteger(N->getOperand(0)); diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -369,6 +369,7 @@ SDValue PromoteIntOp_INSERT_VECTOR_ELT(SDNode *N, unsigned OpNo); SDValue PromoteIntOp_EXTRACT_VECTOR_ELT(SDNode *N); SDValue PromoteIntOp_EXTRACT_SUBVECTOR(SDNode *N); + SDValue PromoteIntOp_INSERT_SUBVECTOR(SDNode *N); SDValue PromoteIntOp_CONCAT_VECTORS(SDNode *N); SDValue PromoteIntOp_SCALAR_TO_VECTOR(SDNode *N); SDValue PromoteIntOp_SPLAT_VECTOR(SDNode *N); diff --git a/llvm/test/CodeGen/AArch64/sve-insert-vector.ll b/llvm/test/CodeGen/AArch64/sve-insert-vector.ll --- a/llvm/test/CodeGen/AArch64/sve-insert-vector.ll +++ b/llvm/test/CodeGen/AArch64/sve-insert-vector.ll @@ -299,6 +299,21 @@ ret %retval } +; This tests promotion of the input operand to INSERT_SUBVECTOR. +define @insert_nxv8i16_nxv2i16( %vec, %in) nounwind { +; CHECK-LABEL: insert_nxv8i16_nxv2i16: +; CHECK: // %bb.0: +; CHECK-NEXT: uunpklo z2.s, z0.h +; CHECK-NEXT: uunpklo z2.d, z2.s +; CHECK-NEXT: uzp1 z1.s, z2.s, z1.s +; CHECK-NEXT: uunpkhi z0.s, z0.h +; CHECK-NEXT: uzp1 z0.h, z1.h, z0.h +; CHECK-NEXT: ret + %r = call @llvm.experimental.vector.insert.nxv8i16.nxv2i16( %vec, %in, i64 2) + ret %r +} + + ; Fixed length clamping define @insert_fixed_v2i64_nxv2i64( %vec, <2 x i64> %subvec) nounwind #0 { @@ -362,3 +377,5 @@ declare @llvm.experimental.vector.insert.v2i64.nxv16i64(, <2 x i64>, i64) declare @llvm.experimental.vector.insert.nxv4i32.nxv1i32(, , i64) declare @llvm.experimental.vector.insert.nxv6i16.nxv1i16(, , i64) + +declare @llvm.experimental.vector.insert.nxv8i16.nxv2i16(, , i64)