diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 9687a52cdab..dc23151bddd 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1968,19 +1968,31 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, case ISD::EXTRACT_VECTOR_ELT: assert(N2C && "Bad EXTRACT_VECTOR_ELT!"); - // EXTRACT_VECTOR_ELT of BUILD_PAIR is often formed while lowering is + // EXTRACT_VECTOR_ELT of CONCAT_VECTORS is often formed while lowering is // expanding copies of large vectors from registers. - if (N1.getOpcode() == ISD::BUILD_PAIR) { - unsigned NewNumElts = MVT::getVectorNumElements(N1.getValueType()) / 2; - bool Low = N2C->getValue() < NewNumElts; - return getNode(ISD::EXTRACT_VECTOR_ELT, VT, N1.getOperand(!Low), - Low ? N2 : getConstant(N2C->getValue() - NewNumElts, - N2.getValueType())); + if (N1.getOpcode() == ISD::CONCAT_VECTORS && + N1.getNumOperands() > 0) { + unsigned Factor = + MVT::getVectorNumElements(N1.getOperand(0).getValueType()); + return getNode(ISD::EXTRACT_VECTOR_ELT, VT, + N1.getOperand(N2C->getValue() / Factor), + getConstant(N2C->getValue() % Factor, N2.getValueType())); } + // EXTRACT_VECTOR_ELT of BUILD_VECTOR is often formed while lowering is // expanding large vector constants. if (N1.getOpcode() == ISD::BUILD_VECTOR) return N1.getOperand(N2C->getValue()); + + // EXTRACT_VECTOR_ELT of INSERT_VECTOR_ELT is often formed when vector + // operations are lowered to scalars. + if (N1.getOpcode() == ISD::INSERT_VECTOR_ELT) + if (ConstantSDNode *IEC = dyn_cast(N1.getOperand(2))) { + if (IEC == N2C) + return N1.getOperand(1); + else + return getNode(ISD::EXTRACT_VECTOR_ELT, VT, N1.getOperand(0), N2); + } break; case ISD::EXTRACT_ELEMENT: assert(N2C && (unsigned)N2C->getValue() < 2 && "Bad EXTRACT_ELEMENT!"); diff --git a/test/CodeGen/X86/peep-vector-extract-concat.ll b/test/CodeGen/X86/peep-vector-extract-concat.ll new file mode 100644 index 00000000000..6880fc33c9a --- /dev/null +++ b/test/CodeGen/X86/peep-vector-extract-concat.ll @@ -0,0 +1,6 @@ +; RUN: llvm-as < %s | llc -march=x86-64 | grep {shufps \$3, %xmm0, %xmm0} + +define float @foo(<8 x float> %a) { + %c = extractelement <8 x float> %a, i32 3 + ret float %c +} diff --git a/test/CodeGen/X86/peep-vector-extract-insert.ll b/test/CodeGen/X86/peep-vector-extract-insert.ll new file mode 100644 index 00000000000..9aeb4f131f2 --- /dev/null +++ b/test/CodeGen/X86/peep-vector-extract-insert.ll @@ -0,0 +1,12 @@ +; RUN: llvm-as < %s | llc -march=x86-64 | grep {pxor %xmm0, %xmm0} | wc -l | grep 2 + +define float @foo(<4 x float> %a) { + %b = insertelement <4 x float> %a, float 0.0, i32 3 + %c = extractelement <4 x float> %b, i32 3 + ret float %c +} +define float @bar(float %a) { + %b = insertelement <4 x float> , float %a, i32 3 + %c = extractelement <4 x float> %b, i32 2 + ret float %c +}