diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 2744c415322..041340ee53f 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -821,6 +821,56 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { if (Tmp1.Val) Result = Tmp1; } break; + + case ISD::EXTRACT_VECTOR_ELT: + Tmp1 = LegalizeOp(Node->getOperand(0)); + Tmp2 = LegalizeOp(Node->getOperand(1)); + Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2); + // FIXME: LOWER. + break; + + case ISD::VEXTRACT_VECTOR_ELT: + // We know that operand #0 is the Vec vector. If the index is a constant + // or if the invec is a supported hardware type, we can use it. Otherwise, + // lower to a store then an indexed load. + Tmp1 = Node->getOperand(0); + Tmp2 = LegalizeOp(Node->getOperand(1)); + + SDNode *InVal = Tmp1.Val; + unsigned NumElems = cast(*(InVal->op_end()-2))->getValue(); + MVT::ValueType EVT = cast(*(InVal->op_end()-1))->getVT(); + + // Figure out if there is a Packed type corresponding to this Vector + // type. If so, convert to the packed type. + MVT::ValueType TVT = MVT::getVectorType(EVT, NumElems); + if (TVT != MVT::Other && TLI.isTypeLegal(TVT)) { + // Turn this into a packed extract_vector_elt operation. + Tmp1 = PackVectorOp(Tmp1, TVT); + Result = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, Node->getValueType(0), + Tmp1, Tmp2); + break; + } else if (NumElems == 1) { + // This must be an access of the only element. + Result = PackVectorOp(Tmp1, EVT); + break; + } else if (ConstantSDNode *CIdx = dyn_cast(Tmp2)) { + SDOperand Lo, Hi; + SplitVectorOp(Tmp1, Lo, Hi); + if (CIdx->getValue() < NumElems/2) { + Tmp1 = Lo; + } else { + Tmp1 = Hi; + Tmp2 = DAG.getConstant(CIdx->getValue() - NumElems/2, + Tmp2.getValueType()); + } + + // It's now an extract from the appropriate high or low part. + Result = LegalizeOp(DAG.UpdateNodeOperands(Result, Tmp1, Tmp2)); + } else { + // FIXME: IMPLEMENT STORE/LOAD lowering. + assert(0 && "unimp!"); + } + break; case ISD::CALLSEQ_START: { SDNode *CallEnd = FindCallEndFromCallStart(Node); @@ -4264,7 +4314,7 @@ SDOperand SelectionDAGLegalize::PackVectorOp(SDOperand Op, MVT::ValueType NewVT) { // FIXME: THIS IS A TEMPORARY HACK if (Op.getValueType() == NewVT) return Op; - + assert(Op.getValueType() == MVT::Vector && "Bad PackVectorOp invocation!"); SDNode *Node = Op.Val; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 8bf499eb7b5..fcca7e355ba 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2671,6 +2671,8 @@ const char *SDNode::getOperationName(const SelectionDAG *G) const { case ISD::SELECT_CC: return "select_cc"; case ISD::INSERT_VECTOR_ELT: return "insert_vector_elt"; case ISD::VINSERT_VECTOR_ELT: return "vinsert_vector_elt"; + case ISD::EXTRACT_VECTOR_ELT: return "extract_vector_elt"; + case ISD::VEXTRACT_VECTOR_ELT: return "vextract_vector_elt"; case ISD::SCALAR_TO_VECTOR: return "scalar_to_vector"; case ISD::VBUILD_VECTOR: return "vbuild_vector"; case ISD::VECTOR_SHUFFLE: return "vector_shuffle"; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index d59184b1e5f..50cb958a6d5 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -463,7 +463,7 @@ public: void visitSetLT(User &I) { visitSetCC(I, ISD::SETLT, ISD::SETULT); } void visitSetGT(User &I) { visitSetCC(I, ISD::SETGT, ISD::SETUGT); } - void visitExtractElement(ExtractElementInst &I) { assert(0 && "TODO"); } + void visitExtractElement(ExtractElementInst &I); void visitInsertElement(InsertElementInst &I); void visitGetElementPtr(User &I); @@ -853,6 +853,14 @@ void SelectionDAGLowering::visitInsertElement(InsertElementInst &I) { InVec, InVal, InIdx, Num, Typ)); } +void SelectionDAGLowering::visitExtractElement(ExtractElementInst &I) { + SDOperand InVec = getValue(I.getOperand(0)); + SDOperand InIdx = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(), + getValue(I.getOperand(1))); + SDOperand Typ = *(InVec.Val->op_end()-1); + setValue(&I, DAG.getNode(ISD::VEXTRACT_VECTOR_ELT, + TLI.getValueType(I.getType()), InVec, InIdx)); +} void SelectionDAGLowering::visitGetElementPtr(User &I) { SDOperand N = getValue(I.getOperand(0));