[llvm] r212514 - [SDAG] Build up a more rich set of APIs for querying build-vector SDAG

Chandler Carruth chandlerc at gmail.com
Tue Jul 8 00:19:55 PDT 2014


Author: chandlerc
Date: Tue Jul  8 02:19:55 2014
New Revision: 212514

URL: http://llvm.org/viewvc/llvm-project?rev=212514&view=rev
Log:
[SDAG] Build up a more rich set of APIs for querying build-vector SDAG
nodes about whether they are splats. This is factored out and improved
from r212324 which got reverted as it was far too aggressive. The new
API should help more conservatively handle buildvectors that are
a mixture of splatted and undef values.

No functionality change at this point. The hope is to slowly
re-introduce the undef-tolerant optimization of splats, but each time
being forced to make a concious decision about how to handle the undefs
in a way that doesn't lead to contradicting assumptions about the
collapsed value.

Hal has pointed out in discussions that this may not end up being the
desired API and instead it may be more convenient to get a mask of the
undef elements or something similar. I'm starting simple and will expand
the API as I adapt actual callers and see exactly what they need.

Modified:
    llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h
    llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp

Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=212514&r1=212513&r2=212514&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h (original)
+++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Tue Jul  8 02:19:55 2014
@@ -1583,11 +1583,16 @@ public:
                        unsigned MinSplatBits = 0,
                        bool isBigEndian = false) const;
 
-  /// getConstantSplatValue - Check if this is a constant splat, and if so,
-  /// return the splat value only if it is a ConstantSDNode. Otherwise
-  /// return nullptr. This is a simpler form of isConstantSplat.
-  /// Get the constant splat only if you care about the splat value.
-  ConstantSDNode *getConstantSplatValue() const;
+  /// \brief Returns the splatted value or a null value if this is not a splat.
+  SDValue getSplatValue(bool &HasUndefElements) const;
+
+  /// \brief Returns the splatted constant or null if this is not a constant
+  /// splat.
+  ConstantSDNode *getConstantSplatNode(bool &HasUndefElements) const;
+
+  /// \brief Returns the splatted constant FP or null if this is not a constant
+  /// FP splat.
+  ConstantFPSDNode *getConstantFPSplatNode(bool &HasUndefElements) const;
 
   bool isConstant() const;
 

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=212514&r1=212513&r2=212514&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Tue Jul  8 02:19:55 2014
@@ -655,10 +655,14 @@ static ConstantSDNode *isConstOrConstSpl
     return CN;
 
   if (BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(N)) {
-    ConstantSDNode *CN = BV->getConstantSplatValue();
+    bool HasUndefElements;
+    ConstantSDNode *CN = BV->getConstantSplatNode(HasUndefElements);
 
     // BuildVectors can truncate their operands. Ignore that case here.
-    if (CN && CN->getValueType(0) == N.getValueType().getScalarType())
+    // FIXME: We blindly ignore splats which include undef which is overly
+    // pessimistic.
+    if (CN && !HasUndefElements &&
+        CN->getValueType(0) == N.getValueType().getScalarType())
       return CN;
   }
 

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=212514&r1=212513&r2=212514&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Tue Jul  8 02:19:55 2014
@@ -1506,8 +1506,10 @@ SDValue SelectionDAG::getVectorShuffle(E
     return N1;
 
   // Shuffling a constant splat doesn't change the result.
+  bool SplatHasUndefs;
   if (N2Undef && N1.getOpcode() == ISD::BUILD_VECTOR)
-    if (cast<BuildVectorSDNode>(N1)->getConstantSplatValue())
+    if (cast<BuildVectorSDNode>(N1)->getConstantSplatNode(SplatHasUndefs) &&
+        !SplatHasUndefs)
       return N1;
 
   FoldingSetNodeID ID;
@@ -6603,16 +6605,38 @@ bool BuildVectorSDNode::isConstantSplat(
   return true;
 }
 
-ConstantSDNode *BuildVectorSDNode::getConstantSplatValue() const {
-  SDValue Op0 = getOperand(0);
-  if (Op0.getOpcode() != ISD::Constant)
-    return nullptr;
-
-  for (unsigned i = 1, e = getNumOperands(); i != e; ++i)
-    if (getOperand(i) != Op0)
-      return nullptr;
+SDValue BuildVectorSDNode::getSplatValue(bool &HasUndefElements) const {
+  HasUndefElements = false;
+  SDValue Splatted;
+  for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
+    SDValue Op = getOperand(i);
+    if (Op.getOpcode() == ISD::UNDEF)
+      HasUndefElements = true;
+    else if (!Splatted)
+      Splatted = Op;
+    else if (Splatted != Op)
+      return SDValue();
+  }
+
+  if (!Splatted) {
+    assert(getOperand(0).getOpcode() == ISD::UNDEF &&
+           "Can only have a splat without a constant for all undefs.");
+    return getOperand(0);
+  }
+
+  return Splatted;
+}
+
+ConstantSDNode *
+BuildVectorSDNode::getConstantSplatNode(bool &HasUndefElements) const {
+  return dyn_cast_or_null<ConstantSDNode>(
+      getSplatValue(HasUndefElements).getNode());
+}
 
-  return cast<ConstantSDNode>(Op0);
+ConstantFPSDNode *
+BuildVectorSDNode::getConstantFPSplatNode(bool &HasUndefElements) const {
+  return dyn_cast_or_null<ConstantFPSDNode>(
+      getSplatValue(HasUndefElements).getNode());
 }
 
 bool BuildVectorSDNode::isConstant() const {

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp?rev=212514&r1=212513&r2=212514&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp Tue Jul  8 02:19:55 2014
@@ -1158,7 +1158,10 @@ bool TargetLowering::isConstTrueVal(cons
       return false;
 
     IsVec = true;
-    CN = BV->getConstantSplatValue();
+    bool HasUndefElements;
+    CN = BV->getConstantSplatNode(HasUndefElements);
+    if (HasUndefElements)
+      return false; // Can't blindly collapse the undef values.
   }
 
   switch (getBooleanContents(IsVec)) {
@@ -1185,7 +1188,10 @@ bool TargetLowering::isConstFalseVal(con
       return false;
 
     IsVec = true;
-    CN = BV->getConstantSplatValue();
+    bool HasUndefElements;
+    CN = BV->getConstantSplatNode(HasUndefElements);
+    if (HasUndefElements)
+      return false; // Can't blindly collapse the undef values.
   }
 
   if (getBooleanContents(IsVec) == UndefinedBooleanContent)





More information about the llvm-commits mailing list