summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2019-04-11 14:21:57 +0000
committerSanjay Patel <spatel@rotateright.com>2019-04-11 14:21:57 +0000
commitc0f4a35e68af0af8301ec0c0070f8a0d665b157f (patch)
tree59ea60da31dade361f36ed65f7b7000f31d85ab8 /llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
parent8ddfd46c61ab1acf27b3100db5e5720590fb0743 (diff)
downloadbcm5719-llvm-c0f4a35e68af0af8301ec0c0070f8a0d665b157f.tar.gz
bcm5719-llvm-c0f4a35e68af0af8301ec0c0070f8a0d665b157f.zip
[DAGCombiner][x86] scalarize inserted vector FP ops
// bo (build_vec ...undef, x, undef...), (build_vec ...undef, y, undef...) --> // build_vec ...undef, (bo x, y), undef... The lifetime of the nodes in these examples is different for variables versus constants, but they are all build vectors briefly, so I'm proposing to catch them in this form to handle all of the leading examples in the motivating test file. Before we have build vectors, we might have insert_vector_element. After that, we might have scalar_to_vector and constant pool loads. It's going to take more work to ensure that FP vector operands are getting simplified with undef elements, so this transform can apply more widely. In a non-loose FP environment, we are likely simplifying FP elements to NaN values rather than undefs. We also need to allow more opcodes down this path. Eg, we don't handle FP min/max flavors yet. Differential Revision: https://reviews.llvm.org/D60514 llvm-svn: 358172
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp58
1 files changed, 58 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index c61b24f8d21..6424f30b310 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -18675,6 +18675,61 @@ SDValue DAGCombiner::XformToShuffleWithZero(SDNode *N) {
return SDValue();
}
+/// If a vector binop is performed on build vector operands that only have one
+/// non-undef element, it may be profitable to extract, scalarize, and insert.
+static SDValue scalarizeBinOpOfBuildVectors(SDNode *N, SelectionDAG &DAG) {
+ SDValue N0 = N->getOperand(0);
+ SDValue N1 = N->getOperand(1);
+ if (N0.getOpcode() != ISD::BUILD_VECTOR || N0.getOpcode() != N1.getOpcode())
+ return SDValue();
+
+ // Return the index of exactly one scalar element in an otherwise undefined
+ // build vector.
+ auto getScalarIndex = [](SDValue V) {
+ int NotUndefIndex = -1;
+ for (unsigned i = 0, e = V.getNumOperands(); i != e; ++i) {
+ // Ignore undef elements.
+ if (V.getOperand(i).isUndef())
+ continue;
+ // There can be only one.
+ if (NotUndefIndex >= 0)
+ return -1;
+ // This might be the only non-undef operand.
+ NotUndefIndex = i;
+ }
+ return NotUndefIndex;
+ };
+ int N0Index = getScalarIndex(N0);
+ if (N0Index == -1)
+ return SDValue();
+ int N1Index = getScalarIndex(N1);
+ if (N1Index == -1)
+ return SDValue();
+
+ SDValue X = N0.getOperand(N0Index);
+ SDValue Y = N1.getOperand(N1Index);
+ EVT ScalarVT = X.getValueType();
+ if (ScalarVT != Y.getValueType())
+ return SDValue();
+
+ // TODO: Remove/replace the extract cost check? If the elements are available
+ // as scalars, then there may be no extract cost. Should we ask if
+ // inserting a scalar back into a vector is cheap instead?
+ EVT VT = N->getValueType(0);
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+ if (N0Index != N1Index || !TLI.isExtractVecEltCheap(VT, N0Index) ||
+ !TLI.isOperationLegalOrCustom(N->getOpcode(), ScalarVT))
+ return SDValue();
+
+ // bo (build_vec ...undef, x, undef...), (build_vec ...undef, y, undef...) -->
+ // build_vec ...undef, (bo x, y), undef...
+ SDValue ScalarBO = DAG.getNode(N->getOpcode(), SDLoc(N), ScalarVT, X, Y,
+ N->getFlags());
+ SmallVector<SDValue, 8> Ops(N0.getNumOperands(), DAG.getUNDEF(ScalarVT));
+ Ops[N0Index] = ScalarBO;
+ return DAG.getBuildVector(VT, SDLoc(N), Ops);
+}
+
/// Visit a binary vector operation, like ADD.
SDValue DAGCombiner::SimplifyVBinOp(SDNode *N) {
assert(N->getValueType(0).isVector() &&
@@ -18737,6 +18792,9 @@ SDValue DAGCombiner::SimplifyVBinOp(SDNode *N) {
}
}
+ if (SDValue V = scalarizeBinOpOfBuildVectors(N, DAG))
+ return V;
+
return SDValue();
}
OpenPOWER on IntegriCloud