summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2014-07-08 07:19:55 +0000
committerChandler Carruth <chandlerc@gmail.com>2014-07-08 07:19:55 +0000
commitb844e72e8548a4afc8b69664fef31d2672bae28c (patch)
treec443c4dd0b2912ed6e77b84fdf0fb827999548e9 /llvm/lib/CodeGen
parent3f0a360f1823927d4f2a85f4d9f10b56c9dcda0d (diff)
downloadbcm5719-llvm-b844e72e8548a4afc8b69664fef31d2672bae28c.tar.gz
bcm5719-llvm-b844e72e8548a4afc8b69664fef31d2672bae28c.zip
[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. llvm-svn: 212514
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp8
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp42
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp10
3 files changed, 47 insertions, 13 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 7198203036b..5d2b02b4bff 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -655,10 +655,14 @@ static ConstantSDNode *isConstOrConstSplat(SDValue N) {
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;
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 3a8a5f9601f..e41d459f39d 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -1506,8 +1506,10 @@ SDValue SelectionDAG::getVectorShuffle(EVT VT, SDLoc dl, SDValue N1,
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(APInt &SplatValue,
return true;
}
-ConstantSDNode *BuildVectorSDNode::getConstantSplatValue() const {
- SDValue Op0 = getOperand(0);
- if (Op0.getOpcode() != ISD::Constant)
- 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();
+ }
- for (unsigned i = 1, e = getNumOperands(); i != e; ++i)
- if (getOperand(i) != Op0)
- return nullptr;
+ 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 {
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index ad91d4a87c1..74de034777d 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -1158,7 +1158,10 @@ bool TargetLowering::isConstTrueVal(const SDNode *N) const {
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(const SDNode *N) const {
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)
OpenPOWER on IntegriCloud