Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -17825,6 +17825,41 @@ return DAG.getVectorShuffle(VT, dl, LHS, RHS, &ShuffleMask[0]); } +// This function assumes all the vselect's arguments are CONCAT_VECTOR +// nodes and that the condition is a BV of ConstantSDNodes (or undefs). +static SDValue ConvertSelecttoConcatVector(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const X86Subtarget *Subtarget) { + SDLoc dl(N); + MVT VT = N->getSimpleValueType(0); + int NumElems = VT.getVectorNumElements(); + SDValue Cond = N->getOperand(0); + SDValue LHS = N->getOperand(1); + SDValue RHS = N->getOperand(2); + + // We're sure we have an even number of elements due to the + // concat_vectors we have as arguments to vselect. + ConstantSDNode *BottomHalf = cast(Cond.getOperand(0)); + for (int i = 0; i < NumElems / 2; ++i) { + if (Cond->getOperand(i)->getOpcode() != ISD::UNDEF && + Cond->getOperand(i).getNode() != BottomHalf) + return SDValue(); + } + + ConstantSDNode *TopHalf = + cast(Cond.getOperand(NumElems / 2)); + for (int i = NumElems / 2; i < NumElems; ++i) { + if (Cond->getOperand(i)->getOpcode() != ISD::UNDEF && + Cond->getOperand(i).getNode() != TopHalf) + return SDValue(); + } + + return DAG.getNode( + ISD::CONCAT_VECTORS, dl, VT, + BottomHalf->isNullValue() ? LHS->getOperand(1) : RHS->getOperand(1), + TopHalf->isNullValue() ? LHS->getOperand(0) : RHS->getOperand(0)); +} + /// PerformSELECTCombine - Do target-specific dag combines on SELECT and VSELECT /// nodes. static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG, @@ -17838,6 +17873,14 @@ EVT VT = LHS.getValueType(); const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + if (LHS.getOpcode() == ISD::CONCAT_VECTORS && + RHS.getOpcode() == ISD::CONCAT_VECTORS && + ISD::isBuildVectorOfConstantSDNodes(Cond.getNode())) { + SDValue BV = ConvertSelecttoConcatVector(N, DAG, DCI, Subtarget); + if (BV.getNode()) + return BV; + } + // If we have SSE[12] support, try to form min/max nodes. SSE min/max // instructions match the semantics of the common C idiom x @select_of_shuffles_0(<2 x float> %a0, <2 x float> %b0, <2 x float> %a1, <2 x float> %b1) { +; CHECK-LABEL: select_of_shuffles_0 +; CHECK: movlhps +; CHECK: movlhps +; CHECK: addps + %1 = shufflevector <2 x float> %a0, <2 x float> undef, <4 x i32> + %2 = shufflevector <2 x float> %a1, <2 x float> undef, <4 x i32> + %3 = select <4 x i1> , <4 x float> %2, <4 x float> %1 + %4 = shufflevector <2 x float> %b0, <2 x float> undef, <4 x i32> + %5 = shufflevector <2 x float> %b1, <2 x float> undef, <4 x i32> + %6 = select <4 x i1> , <4 x float> %5, <4 x float> %4 + %7 = fadd <4 x float> %3, %6 + ret <4 x float> %7 +} + +define <4 x float> @select_of_shuffles_1(<2 x float> %a0, <2 x float> %b0, <2 x float> %a1, <2 x float> %b1) { +; CHECK-LABEL: select_of_shuffles_1 +; CHECK: addps +; CHECK: addps +; CHECK: movlhps + %1 = fadd <2 x float> %a0, %b0 + %2 = shufflevector <2 x float> %1, <2 x float> undef, <4 x i32> + %3 = fadd <2 x float> %a1, %b1 + %4 = shufflevector <2 x float> %3, <2 x float> undef, <4 x i32> + %5 = select <4 x i1> , <4 x float> %4, <4 x float> %2 + ret <4 x float> %5 +} + +define <4 x float> @select_of_shuffles_2(<2 x float> %a0, <2 x float> %b0, <2 x float> %a1, <2 x float> %b1) { +; CHECK-LABEL: select_of_shuffles_2 +; CHECK: movlhps +; CHECK: movlhps +; CHECK: addps + %1 = shufflevector <2 x float> %a0, <2 x float> %a1, <4 x i32> + %2 = shufflevector <2 x float> %b0, <2 x float> %b1, <4 x i32> + %3 = fadd <4 x float> %1, %2 + ret <4 x float> %3 +}