diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index d4af722e7e4..edbd9f3e1ef 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2844,18 +2844,20 @@ static SDValue FoldCONCAT_VECTORS(SDLoc DL, EVT VT, ArrayRef Ops, [](SDValue Op) { return Op.isUndef(); })) return DAG.getUNDEF(VT); - // A CONCAT_VECTOR with all operands BUILD_VECTOR can be simplified - // to one big BUILD_VECTOR. - // FIXME: Add support for UNDEF and SCALAR_TO_VECTOR as well. - if (!std::all_of(Ops.begin(), Ops.end(), [](SDValue Op) { - return Op.getOpcode() == ISD::BUILD_VECTOR; - })) - return SDValue(); - + // A CONCAT_VECTOR with all UNDEF/BUILD_VECTOR operands can be + // simplified to one big BUILD_VECTOR. + // FIXME: Add support for SCALAR_TO_VECTOR as well. EVT SVT = VT.getScalarType(); SmallVector Elts; - for (SDValue Op : Ops) - Elts.append(Op->op_begin(), Op->op_end()); + for (SDValue Op : Ops) { + EVT OpVT = Op.getValueType(); + if (Op.isUndef()) + Elts.append(OpVT.getVectorNumElements(), DAG.getUNDEF(SVT)); + else if (Op.getOpcode() == ISD::BUILD_VECTOR) + Elts.append(Op->op_begin(), Op->op_end()); + else + return SDValue(); + } // BUILD_VECTOR requires all inputs to be of the same type, find the // maximum type and extend them all. diff --git a/test/CodeGen/X86/avx-cast.ll b/test/CodeGen/X86/avx-cast.ll index 34c5dfaa016..8dd3529eb48 100644 --- a/test/CodeGen/X86/avx-cast.ll +++ b/test/CodeGen/X86/avx-cast.ll @@ -31,8 +31,8 @@ define <4 x double> @castB(<2 x double> %m) nounwind uwtable readnone ssp { define <4 x i64> @castC(<2 x i64> %m) nounwind uwtable readnone ssp { ; AVX1-LABEL: castC: ; AVX1: ## BB#0: -; AVX1-NEXT: vxorps %ymm1, %ymm1, %ymm1 -; AVX1-NEXT: vblendps {{.*#+}} ymm0 = ymm0[0,1,2,3],ymm1[4,5,6,7] +; AVX1-NEXT: vxorpd %ymm1, %ymm1, %ymm1 +; AVX1-NEXT: vblendpd {{.*#+}} ymm0 = ymm0[0,1],ymm1[2,3] ; AVX1-NEXT: retq ; ; AVX2-LABEL: castC: