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

Evan Cheng evan.cheng at apple.com
Thu Mar 23 17:17:34 PST 2006



Changes in directory llvm/lib/CodeGen/SelectionDAG:

LegalizeDAG.cpp updated: 1.334 -> 1.335
---
Log message:

Lower BUILD_VECTOR to VECTOR_SHUFFLE if there are two distinct nodes (and if
the target can handle it). Issue two SCALAR_TO_VECTOR ops followed by a
VECTOR_SHUFFLE to select from the two vectors.


---
Diffs of the changes:  (+49 -8)

 LegalizeDAG.cpp |   57 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 49 insertions(+), 8 deletions(-)


Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.334 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.335
--- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.334	Thu Mar 23 15:16:34 2006
+++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp	Thu Mar 23 19:17:21 2006
@@ -21,7 +21,7 @@
 #include "llvm/CallingConv.h"
 #include "llvm/Constants.h"
 #include <iostream>
-#include <set>
+#include <map>
 using namespace llvm;
 
 //===----------------------------------------------------------------------===//
@@ -3070,13 +3070,21 @@
   
   // If the only non-undef value is the low element, turn this into a 
   // SCALAR_TO_VECTOR node.  If this is { X, X, X, X }, determine X.
+  unsigned NumElems = Node->getNumOperands();
   bool isOnlyLowElement = true;
   SDOperand SplatValue = Node->getOperand(0);
-  for (SDNode::op_iterator I = Node->op_begin()+1, E = Node->op_end();
-       I != E; ++I) {
-    if (I->getOpcode() != ISD::UNDEF)
+  std::map<SDOperand, std::vector<unsigned> > Values;
+  Values[SplatValue].push_back(0);
+  for (unsigned i = 1; i < NumElems; ++i) {
+    SDOperand V = Node->getOperand(i);
+    std::map<SDOperand, std::vector<unsigned> >::iterator I = Values.find(V);
+    if (I != Values.end())
+      I->second.push_back(i);
+    else
+      Values[V].push_back(i);
+    if (V.getOpcode() != ISD::UNDEF)
       isOnlyLowElement = false;
-    if (SplatValue != *I)
+    if (SplatValue != V)
       SplatValue = SDOperand(0,0);
   }
   
@@ -3092,9 +3100,9 @@
   if (SplatValue.Val) {   // Splat of one value?
     // Build the shuffle constant vector: <0, 0, 0, 0>
     MVT::ValueType MaskVT = 
-      MVT::getIntVectorWithNumElements(Node->getNumOperands());
+      MVT::getIntVectorWithNumElements(NumElems);
     SDOperand Zero = DAG.getConstant(0, MVT::getVectorBaseType(MaskVT));
-    std::vector<SDOperand> ZeroVec(Node->getNumOperands(), Zero);
+    std::vector<SDOperand> ZeroVec(NumElems, Zero);
     SDOperand SplatMask = DAG.getNode(ISD::BUILD_VECTOR, MaskVT, ZeroVec);
 
     // If the target supports VECTOR_SHUFFLE and this shuffle mask, use it.
@@ -3128,7 +3136,7 @@
     const Type *OpNTy = 
       MVT::getTypeForValueType(Node->getOperand(0).getValueType());
     std::vector<Constant*> CV;
-    for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) {
+    for (unsigned i = 0, e = NumElems; i != e; ++i) {
       if (ConstantFPSDNode *V = 
           dyn_cast<ConstantFPSDNode>(Node->getOperand(i))) {
         CV.push_back(ConstantFP::get(OpNTy, V->getValue()));
@@ -3145,6 +3153,39 @@
     return DAG.getLoad(VT, DAG.getEntryNode(), CPIdx,
                        DAG.getSrcValue(NULL));
   }
+
+  // If there are only two unique elements, we may be able to turn this into a
+  // vector shuffle.
+  if (Values.size() == 2) {
+    // Build the shuffle constant vector: e.g. <0, 4, 0, 4>
+    MVT::ValueType MaskVT = 
+      MVT::getIntVectorWithNumElements(NumElems);
+    std::vector<SDOperand> MaskVec(NumElems);
+    unsigned i = 0;
+    for (std::map<SDOperand,std::vector<unsigned> >::iterator I=Values.begin(),
+           E = Values.end(); I != E; ++I) {
+      for (std::vector<unsigned>::iterator II = I->second.begin(),
+             EE = I->second.end(); II != EE; ++II)
+        MaskVec[*II] = DAG.getConstant(i, MVT::getVectorBaseType(MaskVT));
+      i += NumElems;
+    }
+    SDOperand ShuffleMask = DAG.getNode(ISD::BUILD_VECTOR, MaskVT, MaskVec);
+
+    // If the target supports VECTOR_SHUFFLE and this shuffle mask, use it.
+    if (TLI.isShuffleLegal(Node->getValueType(0), ShuffleMask)) {
+      std::vector<SDOperand> Ops;
+      for(std::map<SDOperand,std::vector<unsigned> >::iterator I=Values.begin(),
+            E = Values.end(); I != E; ++I) {
+        SDOperand Op = DAG.getNode(ISD::SCALAR_TO_VECTOR, Node->getValueType(0),
+                                   I->first);
+        Ops.push_back(Op);
+      }
+      Ops.push_back(ShuffleMask);
+
+      // Return shuffle(LoValVec, HiValVec, <0,1,0,1>)
+      return DAG.getNode(ISD::VECTOR_SHUFFLE, Node->getValueType(0), Ops);
+    }
+  }
   
   // Otherwise, we can't handle this case efficiently.  Allocate a sufficiently
   // aligned object on the stack, store each element into it, then load






More information about the llvm-commits mailing list