diff options
Diffstat (limited to 'llvm/lib/CodeGen')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 52 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 10 | 
3 files changed, 62 insertions, 2 deletions
| diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 2744c415322..041340ee53f 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/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<ConstantSDNode>(*(InVal->op_end()-2))->getValue(); +    MVT::ValueType EVT = cast<VTSDNode>(*(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<ConstantSDNode>(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/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 8bf499eb7b5..fcca7e355ba 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/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/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index d59184b1e5f..50cb958a6d5 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/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)); | 

