Changes in directory llvm/lib/CodeGen/SelectionDAG:
DAGCombiner.cpp updated: 1.130 -> 1.131 --- Log message: Turn a series of extract_element's feeding a build_vector into a vector_shuffle node. For this: void test(__m128 *res, __m128 *A, __m128 *B) { *res = _mm_unpacklo_ps(*A, *B); } we now produce this code: _test: movl 8(%esp), %eax movaps (%eax), %xmm0 movl 12(%esp), %eax unpcklps (%eax), %xmm0 movl 4(%esp), %eax movaps %xmm0, (%eax) ret instead of this: _test: subl $76, %esp movl 88(%esp), %eax movaps (%eax), %xmm0 movaps %xmm0, (%esp) movaps %xmm0, 32(%esp) movss 4(%esp), %xmm0 movss 32(%esp), %xmm1 unpcklps %xmm0, %xmm1 movl 84(%esp), %eax movaps (%eax), %xmm0 movaps %xmm0, 16(%esp) movaps %xmm0, 48(%esp) movss 20(%esp), %xmm0 movss 48(%esp), %xmm2 unpcklps %xmm0, %xmm2 unpcklps %xmm1, %xmm2 movl 80(%esp), %eax movaps %xmm2, (%eax) addl $76, %esp ret GCC produces this (with -fomit-frame-pointer): _test: subl $12, %esp movl 20(%esp), %eax movaps (%eax), %xmm0 movl 24(%esp), %eax unpcklps (%eax), %xmm0 movl 16(%esp), %eax movaps %xmm0, (%eax) addl $12, %esp ret --- Diffs of the changes: (+86 -0) DAGCombiner.cpp | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 86 insertions(+) Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.130 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.131 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.130 Tue Mar 28 13:11:05 2006 +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Tue Mar 28 14:28:38 2006 @@ -211,6 +211,7 @@ SDOperand visitSTORE(SDNode *N); SDOperand visitINSERT_VECTOR_ELT(SDNode *N); SDOperand visitVINSERT_VECTOR_ELT(SDNode *N); + SDOperand visitVBUILD_VECTOR(SDNode *N); SDOperand ReassociateOps(unsigned Opc, SDOperand LHS, SDOperand RHS); @@ -644,6 +645,7 @@ case ISD::STORE: return visitSTORE(N); case ISD::INSERT_VECTOR_ELT: return visitINSERT_VECTOR_ELT(N); case ISD::VINSERT_VECTOR_ELT: return visitVINSERT_VECTOR_ELT(N); + case ISD::VBUILD_VECTOR: return visitVBUILD_VECTOR(N); } return SDOperand(); } @@ -2341,6 +2343,90 @@ return SDOperand(); } +SDOperand DAGCombiner::visitVBUILD_VECTOR(SDNode *N) { + unsigned NumInScalars = N->getNumOperands()-2; + SDOperand NumElts = N->getOperand(NumInScalars); + SDOperand EltType = N->getOperand(NumInScalars+1); + + // Check to see if this is a VBUILD_VECTOR of a bunch of VEXTRACT_VECTOR_ELT + // operations. If so, and if the EXTRACT_ELT vector inputs come from at most + // two distinct vectors, turn this into a shuffle node. + SDOperand VecIn1, VecIn2; + for (unsigned i = 0; i != NumInScalars; ++i) { + // Ignore undef inputs. + if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue; + + // If this input is something other than a VEXTRACT_VECTOR_ELT with a + // constant index, bail out. + if (N->getOperand(i).getOpcode() != ISD::VEXTRACT_VECTOR_ELT || + !isa<ConstantSDNode>(N->getOperand(i).getOperand(1))) { + VecIn1 = VecIn2 = SDOperand(0, 0); + break; + } + + // If the input vector type disagrees with the result of the vbuild_vector, + // we can't make a shuffle. + SDOperand ExtractedFromVec = N->getOperand(i).getOperand(0); + if (*(ExtractedFromVec.Val->op_end()-2) != NumElts || + *(ExtractedFromVec.Val->op_end()-1) != EltType) { + VecIn1 = VecIn2 = SDOperand(0, 0); + break; + } + + // Otherwise, remember this. We allow up to two distinct input vectors. + if (ExtractedFromVec == VecIn1 || ExtractedFromVec == VecIn2) + continue; + + if (VecIn1.Val == 0) { + VecIn1 = ExtractedFromVec; + } else if (VecIn2.Val == 0) { + VecIn2 = ExtractedFromVec; + } else { + // Too many inputs. + VecIn1 = VecIn2 = SDOperand(0, 0); + break; + } + } + + // If everything is good, we can make a shuffle operation. + if (VecIn1.Val) { + std::vector<SDOperand> BuildVecIndices; + for (unsigned i = 0; i != NumInScalars; ++i) { + if (N->getOperand(i).getOpcode() == ISD::UNDEF) { + BuildVecIndices.push_back(DAG.getNode(ISD::UNDEF, MVT::i32)); + continue; + } + + SDOperand Extract = N->getOperand(i); + + // If extracting from the first vector, just use the index directly. + if (Extract.getOperand(0) == VecIn1) { + BuildVecIndices.push_back(Extract.getOperand(1)); + continue; + } + + // Otherwise, use InIdx + VecSize + unsigned Idx = cast<ConstantSDNode>(Extract.getOperand(1))->getValue(); + BuildVecIndices.push_back(DAG.getConstant(Idx+NumInScalars, MVT::i32)); + } + + // Add count and size info. + BuildVecIndices.push_back(NumElts); + BuildVecIndices.push_back(DAG.getValueType(MVT::i32)); + + // Return the new VVECTOR_SHUFFLE node. + std::vector<SDOperand> Ops; + Ops.push_back(VecIn1); + Ops.push_back(VecIn2.Val ? VecIn2 : VecIn1); // Use V1 twice if no V2. + Ops.push_back(DAG.getNode(ISD::VBUILD_VECTOR,MVT::Vector, BuildVecIndices)); + Ops.push_back(NumElts); + Ops.push_back(EltType); + return DAG.getNode(ISD::VVECTOR_SHUFFLE, MVT::Vector, Ops); + } + + return SDOperand(); +} + SDOperand DAGCombiner::SimplifySelect(SDOperand N0, SDOperand N1, SDOperand N2){ assert(N0.getOpcode() ==ISD::SETCC && "First argument must be a SetCC node!"); _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits