mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-10 04:33:40 +00:00
Make it possible for a target to mark FSUB as Expand. This requires providing a default expansion (FADD+FNEG), and teaching DAGCombine not to form FSUBs post-legalize if they are not legal.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152079 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4f92b5e616
commit
afd3d56b9d
@ -381,6 +381,7 @@ CommitTargetLoweringOpt(const TargetLowering::TargetLoweringOpt &TLO) {
|
||||
/// specified expression for the same cost as the expression itself, or 2 if we
|
||||
/// can compute the negated form more cheaply than the expression itself.
|
||||
static char isNegatibleForFree(SDValue Op, bool LegalOperations,
|
||||
const TargetLowering &TLI,
|
||||
const TargetOptions *Options,
|
||||
unsigned Depth = 0) {
|
||||
// No compile time optimizations on this type.
|
||||
@ -406,12 +407,17 @@ static char isNegatibleForFree(SDValue Op, bool LegalOperations,
|
||||
// FIXME: determine better conditions for this xform.
|
||||
if (!Options->UnsafeFPMath) return 0;
|
||||
|
||||
// After operation legalization, it might not be legal to create new FSUBs.
|
||||
if (LegalOperations &&
|
||||
!TLI.isOperationLegalOrCustom(ISD::FSUB, Op.getValueType()))
|
||||
return 0;
|
||||
|
||||
// fold (fsub (fadd A, B)) -> (fsub (fneg A), B)
|
||||
if (char V = isNegatibleForFree(Op.getOperand(0), LegalOperations, Options,
|
||||
Depth + 1))
|
||||
if (char V = isNegatibleForFree(Op.getOperand(0), LegalOperations, TLI,
|
||||
Options, Depth + 1))
|
||||
return V;
|
||||
// fold (fneg (fadd A, B)) -> (fsub (fneg B), A)
|
||||
return isNegatibleForFree(Op.getOperand(1), LegalOperations, Options,
|
||||
return isNegatibleForFree(Op.getOperand(1), LegalOperations, TLI, Options,
|
||||
Depth + 1);
|
||||
case ISD::FSUB:
|
||||
// We can't turn -(A-B) into B-A when we honor signed zeros.
|
||||
@ -425,17 +431,17 @@ static char isNegatibleForFree(SDValue Op, bool LegalOperations,
|
||||
if (Options->HonorSignDependentRoundingFPMath()) return 0;
|
||||
|
||||
// fold (fneg (fmul X, Y)) -> (fmul (fneg X), Y) or (fmul X, (fneg Y))
|
||||
if (char V = isNegatibleForFree(Op.getOperand(0), LegalOperations, Options,
|
||||
Depth + 1))
|
||||
if (char V = isNegatibleForFree(Op.getOperand(0), LegalOperations, TLI,
|
||||
Options, Depth + 1))
|
||||
return V;
|
||||
|
||||
return isNegatibleForFree(Op.getOperand(1), LegalOperations, Options,
|
||||
return isNegatibleForFree(Op.getOperand(1), LegalOperations, TLI, Options,
|
||||
Depth + 1);
|
||||
|
||||
case ISD::FP_EXTEND:
|
||||
case ISD::FP_ROUND:
|
||||
case ISD::FSIN:
|
||||
return isNegatibleForFree(Op.getOperand(0), LegalOperations, Options,
|
||||
return isNegatibleForFree(Op.getOperand(0), LegalOperations, TLI, Options,
|
||||
Depth + 1);
|
||||
}
|
||||
}
|
||||
@ -464,6 +470,7 @@ static SDValue GetNegatedExpression(SDValue Op, SelectionDAG &DAG,
|
||||
|
||||
// fold (fneg (fadd A, B)) -> (fsub (fneg A), B)
|
||||
if (isNegatibleForFree(Op.getOperand(0), LegalOperations,
|
||||
DAG.getTargetLoweringInfo(),
|
||||
&DAG.getTarget().Options, Depth+1))
|
||||
return DAG.getNode(ISD::FSUB, Op.getDebugLoc(), Op.getValueType(),
|
||||
GetNegatedExpression(Op.getOperand(0), DAG,
|
||||
@ -493,6 +500,7 @@ static SDValue GetNegatedExpression(SDValue Op, SelectionDAG &DAG,
|
||||
|
||||
// fold (fneg (fmul X, Y)) -> (fmul (fneg X), Y)
|
||||
if (isNegatibleForFree(Op.getOperand(0), LegalOperations,
|
||||
DAG.getTargetLoweringInfo(),
|
||||
&DAG.getTarget().Options, Depth+1))
|
||||
return DAG.getNode(Op.getOpcode(), Op.getDebugLoc(), Op.getValueType(),
|
||||
GetNegatedExpression(Op.getOperand(0), DAG,
|
||||
@ -5507,11 +5515,13 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {
|
||||
N1CFP->getValueAPF().isZero())
|
||||
return N0;
|
||||
// fold (fadd A, (fneg B)) -> (fsub A, B)
|
||||
if (isNegatibleForFree(N1, LegalOperations, &DAG.getTarget().Options) == 2)
|
||||
if ((!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FSUB, VT)) &&
|
||||
isNegatibleForFree(N1, LegalOperations, TLI, &DAG.getTarget().Options) == 2)
|
||||
return DAG.getNode(ISD::FSUB, N->getDebugLoc(), VT, N0,
|
||||
GetNegatedExpression(N1, DAG, LegalOperations));
|
||||
// fold (fadd (fneg A), B) -> (fsub B, A)
|
||||
if (isNegatibleForFree(N0, LegalOperations, &DAG.getTarget().Options) == 2)
|
||||
if ((!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FSUB, VT)) &&
|
||||
isNegatibleForFree(N0, LegalOperations, TLI, &DAG.getTarget().Options) == 2)
|
||||
return DAG.getNode(ISD::FSUB, N->getDebugLoc(), VT, N1,
|
||||
GetNegatedExpression(N0, DAG, LegalOperations));
|
||||
|
||||
@ -5549,13 +5559,13 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {
|
||||
// fold (fsub 0, B) -> -B
|
||||
if (DAG.getTarget().Options.UnsafeFPMath &&
|
||||
N0CFP && N0CFP->getValueAPF().isZero()) {
|
||||
if (isNegatibleForFree(N1, LegalOperations, &DAG.getTarget().Options))
|
||||
if (isNegatibleForFree(N1, LegalOperations, TLI, &DAG.getTarget().Options))
|
||||
return GetNegatedExpression(N1, DAG, LegalOperations);
|
||||
if (!LegalOperations || TLI.isOperationLegal(ISD::FNEG, VT))
|
||||
return DAG.getNode(ISD::FNEG, N->getDebugLoc(), VT, N1);
|
||||
}
|
||||
// fold (fsub A, (fneg B)) -> (fadd A, B)
|
||||
if (isNegatibleForFree(N1, LegalOperations, &DAG.getTarget().Options))
|
||||
if (isNegatibleForFree(N1, LegalOperations, TLI, &DAG.getTarget().Options))
|
||||
return DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, N0,
|
||||
GetNegatedExpression(N1, DAG, LegalOperations));
|
||||
|
||||
@ -5568,6 +5578,7 @@ SDValue DAGCombiner::visitFMUL(SDNode *N) {
|
||||
ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(N0);
|
||||
ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1);
|
||||
EVT VT = N->getValueType(0);
|
||||
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
|
||||
|
||||
// fold vector ops
|
||||
if (VT.isVector()) {
|
||||
@ -5598,9 +5609,9 @@ SDValue DAGCombiner::visitFMUL(SDNode *N) {
|
||||
return DAG.getNode(ISD::FNEG, N->getDebugLoc(), VT, N0);
|
||||
|
||||
// fold (fmul (fneg X), (fneg Y)) -> (fmul X, Y)
|
||||
if (char LHSNeg = isNegatibleForFree(N0, LegalOperations,
|
||||
if (char LHSNeg = isNegatibleForFree(N0, LegalOperations, TLI,
|
||||
&DAG.getTarget().Options)) {
|
||||
if (char RHSNeg = isNegatibleForFree(N1, LegalOperations,
|
||||
if (char RHSNeg = isNegatibleForFree(N1, LegalOperations, TLI,
|
||||
&DAG.getTarget().Options)) {
|
||||
// Both can be negated for free, check to see if at least one is cheaper
|
||||
// negated.
|
||||
@ -5628,6 +5639,7 @@ SDValue DAGCombiner::visitFDIV(SDNode *N) {
|
||||
ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(N0);
|
||||
ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1);
|
||||
EVT VT = N->getValueType(0);
|
||||
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
|
||||
|
||||
// fold vector ops
|
||||
if (VT.isVector()) {
|
||||
@ -5641,9 +5653,9 @@ SDValue DAGCombiner::visitFDIV(SDNode *N) {
|
||||
|
||||
|
||||
// (fdiv (fneg X), (fneg Y)) -> (fdiv X, Y)
|
||||
if (char LHSNeg = isNegatibleForFree(N0, LegalOperations,
|
||||
if (char LHSNeg = isNegatibleForFree(N0, LegalOperations, TLI,
|
||||
&DAG.getTarget().Options)) {
|
||||
if (char RHSNeg = isNegatibleForFree(N1, LegalOperations,
|
||||
if (char RHSNeg = isNegatibleForFree(N1, LegalOperations, TLI,
|
||||
&DAG.getTarget().Options)) {
|
||||
// Both can be negated for free, check to see if at least one is cheaper
|
||||
// negated.
|
||||
@ -5897,7 +5909,8 @@ SDValue DAGCombiner::visitFNEG(SDNode *N) {
|
||||
SDValue N0 = N->getOperand(0);
|
||||
EVT VT = N->getValueType(0);
|
||||
|
||||
if (isNegatibleForFree(N0, LegalOperations, &DAG.getTarget().Options))
|
||||
if (isNegatibleForFree(N0, LegalOperations, DAG.getTargetLoweringInfo(),
|
||||
&DAG.getTarget().Options))
|
||||
return GetNegatedExpression(N0, DAG, LegalOperations);
|
||||
|
||||
// Transform fneg(bitconvert(x)) -> bitconvert(x^sign) to avoid loading
|
||||
|
@ -3032,6 +3032,16 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node) {
|
||||
Results.push_back(Results[0].getValue(1));
|
||||
break;
|
||||
}
|
||||
case ISD::FSUB: {
|
||||
EVT VT = Node->getValueType(0);
|
||||
assert(TLI.isOperationLegalOrCustom(ISD::FADD, VT) &&
|
||||
TLI.isOperationLegalOrCustom(ISD::FNEG, VT) &&
|
||||
"Don't know how to expand this FP subtraction!");
|
||||
Tmp1 = DAG.getNode(ISD::FNEG, dl, VT, Node->getOperand(1));
|
||||
Tmp1 = DAG.getNode(ISD::FADD, dl, VT, Node->getOperand(0), Tmp1);
|
||||
Results.push_back(Tmp1);
|
||||
break;
|
||||
}
|
||||
case ISD::SUB: {
|
||||
EVT VT = Node->getValueType(0);
|
||||
assert(TLI.isOperationLegalOrCustom(ISD::ADD, VT) &&
|
||||
|
Loading…
x
Reference in New Issue
Block a user