diff --git a/llvm/lib/Target/VE/VEISelLowering.cpp b/llvm/lib/Target/VE/VEISelLowering.cpp --- a/llvm/lib/Target/VE/VEISelLowering.cpp +++ b/llvm/lib/Target/VE/VEISelLowering.cpp @@ -1525,6 +1525,29 @@ MachinePointerInfo()); } +static bool getUniqueInsertion(SDNode *N, unsigned &UniqueIdx) { + if (!isa(N)) + return false; + const auto *BVN = cast(N); + + // Find first non-undef insertion. + unsigned Idx; + for (Idx = 0; Idx < BVN->getNumOperands(); ++Idx) { + auto ElemV = BVN->getOperand(Idx); + if (!ElemV->isUndef()) + break; + } + // Remember insertion. + UniqueIdx = Idx++; + // Verify that all other insertions are undef. + for (; Idx < BVN->getNumOperands(); ++Idx) { + auto ElemV = BVN->getOperand(Idx); + if (!ElemV->isUndef()) + return false; + } + return true; +} + static SDValue getSplatValue(SDNode *N) { if (auto *BuildVec = dyn_cast(N)) { return BuildVec->getSplatValue(); @@ -1538,6 +1561,17 @@ unsigned NumEls = Op.getValueType().getVectorNumElements(); MVT ElemVT = Op.getSimpleValueType().getVectorElementType(); + // If there is just one element, expand to INSERT_VECTOR_ELT. + unsigned UniqueIdx; + if (getUniqueInsertion(Op.getNode(), UniqueIdx)) { + SDValue AccuV = DAG.getUNDEF(Op.getValueType()); + auto ElemV = Op->getOperand(UniqueIdx); + SDValue IdxV = DAG.getConstant(UniqueIdx, DL, MVT::i64); + return DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, Op.getValueType(), AccuV, + ElemV, IdxV); + } + + // Else emit a broadcast. if (SDValue ScalarV = getSplatValue(Op.getNode())) { // lower to VEC_BROADCAST MVT LegalResVT = MVT::getVectorVT(ElemVT, 256); diff --git a/llvm/test/CodeGen/VE/Vector/expand_single_elem_build_vec.ll b/llvm/test/CodeGen/VE/Vector/expand_single_elem_build_vec.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/VE/Vector/expand_single_elem_build_vec.ll @@ -0,0 +1,14 @@ +; REQUIRES: asserts +; RUN: not --crash llc %s -march=ve -mattr=+vpu -o /dev/null |& FileCheck %s + +; TODO: Replace this with a better test once insert_vector_elt isel is upstream. + +; CHECK: t{{[0-9]+}}: v256i32 = insert_vector_elt undef:v256i32, [[VAL:t[0-9]+]], Constant:i64<42> +; CHECK: [[VAL]]: i32 + +; Function Attrs: norecurse nounwind readnone +; Check that a single-element insertion is lowered to a insert_vector_elt node for isel. +define <256 x i32> @expand_single_elem_build_vec(i32 %x, i32 %y) { + %r = insertelement <256 x i32> undef, i32 %x, i32 42 + ret <256 x i32> %r +}