group unsafe math folds together for easier reading

Also added a FIXME regarding redundant folds for non-canonicalized constants.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217390 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Sanjay Patel 2014-09-08 17:32:19 +00:00
parent c3c0c6df2a
commit f6ab875af0

View File

@ -6557,177 +6557,169 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {
// fold (fadd c1, c2) -> c1 + c2 // fold (fadd c1, c2) -> c1 + c2
if (N0CFP && N1CFP) if (N0CFP && N1CFP)
return DAG.getNode(ISD::FADD, SDLoc(N), VT, N0, N1); return DAG.getNode(ISD::FADD, SDLoc(N), VT, N0, N1);
// canonicalize constant to RHS // canonicalize constant to RHS
if (N0CFP && !N1CFP) if (N0CFP && !N1CFP)
return DAG.getNode(ISD::FADD, SDLoc(N), VT, N1, N0); return DAG.getNode(ISD::FADD, SDLoc(N), VT, N1, N0);
// fold (fadd A, 0) -> A
if (Options.UnsafeFPMath && N1CFP && N1CFP->getValueAPF().isZero())
return N0;
// fold (fadd A, (fneg B)) -> (fsub A, B) // fold (fadd A, (fneg B)) -> (fsub A, B)
if ((!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FSUB, VT)) && if ((!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FSUB, VT)) &&
isNegatibleForFree(N1, LegalOperations, TLI, &Options) == 2) isNegatibleForFree(N1, LegalOperations, TLI, &Options) == 2)
return DAG.getNode(ISD::FSUB, SDLoc(N), VT, N0, return DAG.getNode(ISD::FSUB, SDLoc(N), VT, N0,
GetNegatedExpression(N1, DAG, LegalOperations)); GetNegatedExpression(N1, DAG, LegalOperations));
// fold (fadd (fneg A), B) -> (fsub B, A) // fold (fadd (fneg A), B) -> (fsub B, A)
if ((!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FSUB, VT)) && if ((!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FSUB, VT)) &&
isNegatibleForFree(N0, LegalOperations, TLI, &Options) == 2) isNegatibleForFree(N0, LegalOperations, TLI, &Options) == 2)
return DAG.getNode(ISD::FSUB, SDLoc(N), VT, N1, return DAG.getNode(ISD::FSUB, SDLoc(N), VT, N1,
GetNegatedExpression(N0, DAG, LegalOperations)); GetNegatedExpression(N0, DAG, LegalOperations));
// If allowed, fold (fadd (fadd x, c1), c2) -> (fadd x, (fadd c1, c2)) // If 'unsafe math' is enabled, fold lots of things.
if (Options.UnsafeFPMath && N1CFP && if (Options.UnsafeFPMath) {
N0.getOpcode() == ISD::FADD && N0.getNode()->hasOneUse() && // No FP constant should be created after legalization as Instruction
isa<ConstantFPSDNode>(N0.getOperand(1))) // Selection pass has a hard time dealing with FP constants.
return DAG.getNode(ISD::FADD, SDLoc(N), VT, N0.getOperand(0), bool AllowNewConst = (Level < AfterLegalizeDAG);
DAG.getNode(ISD::FADD, SDLoc(N), VT,
N0.getOperand(1), N1)); // fold (fadd A, 0) -> A
if (N1CFP && N1CFP->getValueAPF().isZero())
return N0;
// No FP constant should be created after legalization as Instruction // fold (fadd (fadd x, c1), c2) -> (fadd x, (fadd c1, c2))
// Selection pass has hard time in dealing with FP constant. if (N1CFP && N0.getOpcode() == ISD::FADD && N0.getNode()->hasOneUse() &&
// isa<ConstantFPSDNode>(N0.getOperand(1)))
// We don't need test this condition for transformation like following, as return DAG.getNode(ISD::FADD, SDLoc(N), VT, N0.getOperand(0),
// the DAG being transformed implies it is legal to take FP constant as DAG.getNode(ISD::FADD, SDLoc(N), VT,
// operand. N0.getOperand(1), N1));
//
// (fadd (fmul c, x), x) -> (fmul c+1, x) // If allowed, fold (fadd (fneg x), x) -> 0.0
// if (AllowNewConst && N0.getOpcode() == ISD::FNEG && N0.getOperand(0) == N1)
bool AllowNewFpConst = (Level < AfterLegalizeDAG); return DAG.getConstantFP(0.0, VT);
// If allowed, fold (fadd x, (fneg x)) -> 0.0
if (AllowNewConst && N1.getOpcode() == ISD::FNEG && N1.getOperand(0) == N0)
return DAG.getConstantFP(0.0, VT);
// We can fold chains of FADD's of the same value into multiplications.
// This transform is not safe in general because we are reducing the number
// of rounding steps.
// If allow, fold (fadd (fneg x), x) -> 0.0 // FIXME: There are 4 redundant folds below where fmul canonicalization
if (AllowNewFpConst && Options.UnsafeFPMath && // should have moved the constant out of Op0?
N0.getOpcode() == ISD::FNEG && N0.getOperand(0) == N1) if (TLI.isOperationLegalOrCustom(ISD::FMUL, VT) && !N0CFP && !N1CFP) {
return DAG.getConstantFP(0.0, VT); if (N0.getOpcode() == ISD::FMUL) {
ConstantFPSDNode *CFP00 = dyn_cast<ConstantFPSDNode>(N0.getOperand(0));
ConstantFPSDNode *CFP01 = dyn_cast<ConstantFPSDNode>(N0.getOperand(1));
// (fadd (fmul c, x), x) -> (fmul x, c+1)
if (CFP00 && !CFP01 && N0.getOperand(1) == N1) {
SDValue NewCFP = DAG.getNode(ISD::FADD, SDLoc(N), VT,
SDValue(CFP00, 0),
DAG.getConstantFP(1.0, VT));
return DAG.getNode(ISD::FMUL, SDLoc(N), VT, N1, NewCFP);
}
// (fadd (fmul x, c), x) -> (fmul x, c+1)
if (CFP01 && !CFP00 && N0.getOperand(0) == N1) {
SDValue NewCFP = DAG.getNode(ISD::FADD, SDLoc(N), VT,
SDValue(CFP01, 0),
DAG.getConstantFP(1.0, VT));
return DAG.getNode(ISD::FMUL, SDLoc(N), VT, N1, NewCFP);
}
// If allow, fold (fadd x, (fneg x)) -> 0.0 // (fadd (fmul c, x), (fadd x, x)) -> (fmul x, c+2)
if (AllowNewFpConst && Options.UnsafeFPMath && if (CFP00 && !CFP01 && N1.getOpcode() == ISD::FADD &&
N1.getOpcode() == ISD::FNEG && N1.getOperand(0) == N0) N1.getOperand(0) == N1.getOperand(1) &&
return DAG.getConstantFP(0.0, VT); N0.getOperand(1) == N1.getOperand(0)) {
SDValue NewCFP = DAG.getNode(ISD::FADD, SDLoc(N), VT,
// In unsafe math mode, we can fold chains of FADD's of the same value SDValue(CFP00, 0),
// into multiplications. This transform is not safe in general because DAG.getConstantFP(2.0, VT));
// we are reducing the number of rounding steps. return DAG.getNode(ISD::FMUL, SDLoc(N), VT,
if (Options.UnsafeFPMath && TLI.isOperationLegalOrCustom(ISD::FMUL, VT) && N0.getOperand(1), NewCFP);
!N0CFP && !N1CFP) { }
if (N0.getOpcode() == ISD::FMUL) {
ConstantFPSDNode *CFP00 = dyn_cast<ConstantFPSDNode>(N0.getOperand(0)); // (fadd (fmul x, c), (fadd x, x)) -> (fmul x, c+2)
ConstantFPSDNode *CFP01 = dyn_cast<ConstantFPSDNode>(N0.getOperand(1)); if (CFP01 && !CFP00 && N1.getOpcode() == ISD::FADD &&
N1.getOperand(0) == N1.getOperand(1) &&
// (fadd (fmul c, x), x) -> (fmul x, c+1) N0.getOperand(0) == N1.getOperand(0)) {
if (CFP00 && !CFP01 && N0.getOperand(1) == N1) { SDValue NewCFP = DAG.getNode(ISD::FADD, SDLoc(N), VT,
SDValue NewCFP = DAG.getNode(ISD::FADD, SDLoc(N), VT, SDValue(CFP01, 0),
SDValue(CFP00, 0), DAG.getConstantFP(2.0, VT));
DAG.getConstantFP(1.0, VT)); return DAG.getNode(ISD::FMUL, SDLoc(N), VT,
return DAG.getNode(ISD::FMUL, SDLoc(N), VT, N0.getOperand(0), NewCFP);
N1, NewCFP); }
} }
// (fadd (fmul x, c), x) -> (fmul x, c+1) if (N1.getOpcode() == ISD::FMUL) {
if (CFP01 && !CFP00 && N0.getOperand(0) == N1) { ConstantFPSDNode *CFP10 = dyn_cast<ConstantFPSDNode>(N1.getOperand(0));
SDValue NewCFP = DAG.getNode(ISD::FADD, SDLoc(N), VT, ConstantFPSDNode *CFP11 = dyn_cast<ConstantFPSDNode>(N1.getOperand(1));
SDValue(CFP01, 0),
DAG.getConstantFP(1.0, VT)); // (fadd x, (fmul c, x)) -> (fmul x, c+1)
return DAG.getNode(ISD::FMUL, SDLoc(N), VT, if (CFP10 && !CFP11 && N1.getOperand(1) == N0) {
N1, NewCFP); SDValue NewCFP = DAG.getNode(ISD::FADD, SDLoc(N), VT,
SDValue(CFP10, 0),
DAG.getConstantFP(1.0, VT));
return DAG.getNode(ISD::FMUL, SDLoc(N), VT, N0, NewCFP);
}
// (fadd x, (fmul x, c)) -> (fmul x, c+1)
if (CFP11 && !CFP10 && N1.getOperand(0) == N0) {
SDValue NewCFP = DAG.getNode(ISD::FADD, SDLoc(N), VT,
SDValue(CFP11, 0),
DAG.getConstantFP(1.0, VT));
return DAG.getNode(ISD::FMUL, SDLoc(N), VT, N0, NewCFP);
}
// (fadd (fadd x, x), (fmul c, x)) -> (fmul x, c+2)
if (CFP10 && !CFP11 && N0.getOpcode() == ISD::FADD &&
N0.getOperand(0) == N0.getOperand(1) &&
N1.getOperand(1) == N0.getOperand(0)) {
SDValue NewCFP = DAG.getNode(ISD::FADD, SDLoc(N), VT,
SDValue(CFP10, 0),
DAG.getConstantFP(2.0, VT));
return DAG.getNode(ISD::FMUL, SDLoc(N), VT, N1.getOperand(1), NewCFP);
}
// (fadd (fadd x, x), (fmul x, c)) -> (fmul x, c+2)
if (CFP11 && !CFP10 && N0.getOpcode() == ISD::FADD &&
N0.getOperand(0) == N0.getOperand(1) &&
N1.getOperand(0) == N0.getOperand(0)) {
SDValue NewCFP = DAG.getNode(ISD::FADD, SDLoc(N), VT,
SDValue(CFP11, 0),
DAG.getConstantFP(2.0, VT));
return DAG.getNode(ISD::FMUL, SDLoc(N), VT, N1.getOperand(0), NewCFP);
}
} }
// (fadd (fmul c, x), (fadd x, x)) -> (fmul x, c+2) if (N0.getOpcode() == ISD::FADD && AllowNewConst) {
if (CFP00 && !CFP01 && N1.getOpcode() == ISD::FADD && ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(N0.getOperand(0));
N1.getOperand(0) == N1.getOperand(1) && // (fadd (fadd x, x), x) -> (fmul x, 3.0)
N0.getOperand(1) == N1.getOperand(0)) { if (!CFP && N0.getOperand(0) == N0.getOperand(1) &&
SDValue NewCFP = DAG.getNode(ISD::FADD, SDLoc(N), VT, (N0.getOperand(0) == N1))
SDValue(CFP00, 0), return DAG.getNode(ISD::FMUL, SDLoc(N), VT,
DAG.getConstantFP(2.0, VT)); N1, DAG.getConstantFP(3.0, VT));
return DAG.getNode(ISD::FMUL, SDLoc(N), VT,
N0.getOperand(1), NewCFP);
} }
// (fadd (fmul x, c), (fadd x, x)) -> (fmul x, c+2) if (N1.getOpcode() == ISD::FADD && AllowNewConst) {
if (CFP01 && !CFP00 && N1.getOpcode() == ISD::FADD && ConstantFPSDNode *CFP10 = dyn_cast<ConstantFPSDNode>(N1.getOperand(0));
N1.getOperand(0) == N1.getOperand(1) && // (fadd x, (fadd x, x)) -> (fmul x, 3.0)
N0.getOperand(0) == N1.getOperand(0)) { if (!CFP10 && N1.getOperand(0) == N1.getOperand(1) &&
SDValue NewCFP = DAG.getNode(ISD::FADD, SDLoc(N), VT, N1.getOperand(0) == N0)
SDValue(CFP01, 0), return DAG.getNode(ISD::FMUL, SDLoc(N), VT,
DAG.getConstantFP(2.0, VT)); N0, DAG.getConstantFP(3.0, VT));
return DAG.getNode(ISD::FMUL, SDLoc(N), VT,
N0.getOperand(0), NewCFP);
} }
}
// (fadd (fadd x, x), (fadd x, x)) -> (fmul x, 4.0)
if (N1.getOpcode() == ISD::FMUL) { if (AllowNewConst &&
ConstantFPSDNode *CFP10 = dyn_cast<ConstantFPSDNode>(N1.getOperand(0)); N0.getOpcode() == ISD::FADD && N1.getOpcode() == ISD::FADD &&
ConstantFPSDNode *CFP11 = dyn_cast<ConstantFPSDNode>(N1.getOperand(1));
// (fadd x, (fmul c, x)) -> (fmul x, c+1)
if (CFP10 && !CFP11 && N1.getOperand(1) == N0) {
SDValue NewCFP = DAG.getNode(ISD::FADD, SDLoc(N), VT,
SDValue(CFP10, 0),
DAG.getConstantFP(1.0, VT));
return DAG.getNode(ISD::FMUL, SDLoc(N), VT,
N0, NewCFP);
}
// (fadd x, (fmul x, c)) -> (fmul x, c+1)
if (CFP11 && !CFP10 && N1.getOperand(0) == N0) {
SDValue NewCFP = DAG.getNode(ISD::FADD, SDLoc(N), VT,
SDValue(CFP11, 0),
DAG.getConstantFP(1.0, VT));
return DAG.getNode(ISD::FMUL, SDLoc(N), VT,
N0, NewCFP);
}
// (fadd (fadd x, x), (fmul c, x)) -> (fmul x, c+2)
if (CFP10 && !CFP11 && N0.getOpcode() == ISD::FADD &&
N0.getOperand(0) == N0.getOperand(1) && N0.getOperand(0) == N0.getOperand(1) &&
N1.getOperand(1) == N0.getOperand(0)) { N1.getOperand(0) == N1.getOperand(1) &&
SDValue NewCFP = DAG.getNode(ISD::FADD, SDLoc(N), VT, N0.getOperand(0) == N1.getOperand(0))
SDValue(CFP10, 0),
DAG.getConstantFP(2.0, VT));
return DAG.getNode(ISD::FMUL, SDLoc(N), VT, return DAG.getNode(ISD::FMUL, SDLoc(N), VT,
N1.getOperand(1), NewCFP); N0.getOperand(0), DAG.getConstantFP(4.0, VT));
}
// (fadd (fadd x, x), (fmul x, c)) -> (fmul x, c+2)
if (CFP11 && !CFP10 && N0.getOpcode() == ISD::FADD &&
N0.getOperand(0) == N0.getOperand(1) &&
N1.getOperand(0) == N0.getOperand(0)) {
SDValue NewCFP = DAG.getNode(ISD::FADD, SDLoc(N), VT,
SDValue(CFP11, 0),
DAG.getConstantFP(2.0, VT));
return DAG.getNode(ISD::FMUL, SDLoc(N), VT,
N1.getOperand(0), NewCFP);
}
} }
} // enable-unsafe-fp-math
if (N0.getOpcode() == ISD::FADD && AllowNewFpConst) {
ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(N0.getOperand(0));
// (fadd (fadd x, x), x) -> (fmul x, 3.0)
if (!CFP && N0.getOperand(0) == N0.getOperand(1) &&
(N0.getOperand(0) == N1))
return DAG.getNode(ISD::FMUL, SDLoc(N), VT,
N1, DAG.getConstantFP(3.0, VT));
}
if (N1.getOpcode() == ISD::FADD && AllowNewFpConst) {
ConstantFPSDNode *CFP10 = dyn_cast<ConstantFPSDNode>(N1.getOperand(0));
// (fadd x, (fadd x, x)) -> (fmul x, 3.0)
if (!CFP10 && N1.getOperand(0) == N1.getOperand(1) &&
N1.getOperand(0) == N0)
return DAG.getNode(ISD::FMUL, SDLoc(N), VT,
N0, DAG.getConstantFP(3.0, VT));
}
// (fadd (fadd x, x), (fadd x, x)) -> (fmul x, 4.0)
if (AllowNewFpConst &&
N0.getOpcode() == ISD::FADD && N1.getOpcode() == ISD::FADD &&
N0.getOperand(0) == N0.getOperand(1) &&
N1.getOperand(0) == N1.getOperand(1) &&
N0.getOperand(0) == N1.getOperand(0))
return DAG.getNode(ISD::FMUL, SDLoc(N), VT,
N0.getOperand(0),
DAG.getConstantFP(4.0, VT));
}
// FADD -> FMA combines: // FADD -> FMA combines:
if ((Options.AllowFPOpFusion == FPOpFusion::Fast || Options.UnsafeFPMath) && if ((Options.AllowFPOpFusion == FPOpFusion::Fast || Options.UnsafeFPMath) &&
DAG.getTarget() DAG.getTarget()