summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorMatt Arsenault <Matthew.Arsenault@amd.com>2014-08-16 10:14:19 +0000
committerMatt Arsenault <Matthew.Arsenault@amd.com>2014-08-16 10:14:19 +0000
commit6cc00429ff750a815f0c3b48d79a0c6e45f68e55 (patch)
tree3756ac113ddfa8d61582e2b1f8420faab65c86ec /llvm/lib/CodeGen
parente020f117ce2ed990904bbd121b7ddbfdae8013ed (diff)
downloadbcm5719-llvm-6cc00429ff750a815f0c3b48d79a0c6e45f68e55.tar.gz
bcm5719-llvm-6cc00429ff750a815f0c3b48d79a0c6e45f68e55.zip
Fix fmul combines with constant splat vectors
Fixes things like fmul x, 2 -> fadd x, x llvm-svn: 215820
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp33
1 files changed, 26 insertions, 7 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index e9a38b1b437..f6dc9384ee3 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -701,6 +701,27 @@ static ConstantSDNode *isConstOrConstSplat(SDValue N) {
return nullptr;
}
+// \brief Returns the SDNode if it is a constant splat BuildVector or constant
+// float.
+static ConstantFPSDNode *isConstOrConstSplatFP(SDValue N) {
+ if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N))
+ return CN;
+
+ if (BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(N)) {
+ BitVector UndefElements;
+ ConstantFPSDNode *CN = BV->getConstantFPSplatNode(&UndefElements);
+
+ // BuildVectors can truncate their operands. Ignore that case here.
+ // FIXME: We blindly ignore splats which include undef which is overly
+ // pessimistic.
+ if (CN && UndefElements.none() &&
+ CN->getValueType(0) == N.getValueType().getScalarType())
+ return CN;
+ }
+
+ return nullptr;
+}
+
SDValue DAGCombiner::ReassociateOps(unsigned Opc, SDLoc DL,
SDValue N0, SDValue N1) {
EVT VT = N0.getValueType();
@@ -6830,8 +6851,8 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {
SDValue DAGCombiner::visitFMUL(SDNode *N) {
SDValue N0 = N->getOperand(0);
SDValue N1 = N->getOperand(1);
- ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(N0);
- ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1);
+ ConstantFPSDNode *N0CFP = isConstOrConstSplatFP(N0);
+ ConstantFPSDNode *N1CFP = isConstOrConstSplatFP(N1);
EVT VT = N->getValueType(0);
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
@@ -6851,13 +6872,10 @@ SDValue DAGCombiner::visitFMUL(SDNode *N) {
if (DAG.getTarget().Options.UnsafeFPMath &&
N1CFP && N1CFP->getValueAPF().isZero())
return N1;
- // fold (fmul A, 0) -> 0, vector edition.
- if (DAG.getTarget().Options.UnsafeFPMath &&
- ISD::isBuildVectorAllZeros(N1.getNode()))
- return N1;
// fold (fmul A, 1.0) -> A
if (N1CFP && N1CFP->isExactlyValue(1.0))
return N0;
+
// fold (fmul X, 2.0) -> (fadd X, X)
if (N1CFP && N1CFP->isExactlyValue(+2.0))
return DAG.getNode(ISD::FADD, SDLoc(N), VT, N0, N0);
@@ -6883,10 +6901,11 @@ SDValue DAGCombiner::visitFMUL(SDNode *N) {
// If allowed, fold (fmul (fmul x, c1), c2) -> (fmul x, (fmul c1, c2))
if (DAG.getTarget().Options.UnsafeFPMath &&
N1CFP && N0.getOpcode() == ISD::FMUL &&
- N0.getNode()->hasOneUse() && isa<ConstantFPSDNode>(N0.getOperand(1)))
+ N0.getNode()->hasOneUse() && isConstOrConstSplatFP(N0.getOperand(1))) {
return DAG.getNode(ISD::FMUL, SDLoc(N), VT, N0.getOperand(0),
DAG.getNode(ISD::FMUL, SDLoc(N), VT,
N0.getOperand(1), N1));
+ }
return SDValue();
}
OpenPOWER on IntegriCloud