[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Chris Lattner lattner at cs.uiuc.edu
Tue Mar 28 12:28:49 PST 2006



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!");
   






More information about the llvm-commits mailing list