mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
[TargetLowering] Add NegatibleCost enum for isNegatibleForFree return codes
The isNegatibleForFree/getNegatedExpression methods currently rely on a raw char value to indicate whether a negation is beneficial or not. This patch replaces the char return value with an NegatibleCost enum to more clearly demonstrate what is implied. It also renames isNegatibleForFree to getNegatibleCost to more accurately reflect whats going on. Differential Revision: https://reviews.llvm.org/D74221
This commit is contained in:
parent
f20c2cef4e
commit
714eb197b4
@ -255,6 +255,13 @@ public:
|
||||
// or custom.
|
||||
};
|
||||
|
||||
/// Enum that specifies when a float negation is beneficial.
|
||||
enum class NegatibleCost {
|
||||
Expensive = 0, // Negated expression is more expensive.
|
||||
Neutral = 1, // Negated expression has the same cost.
|
||||
Cheaper = 2 // Negated expression is cheaper.
|
||||
};
|
||||
|
||||
class ArgListEntry {
|
||||
public:
|
||||
Value *Val = nullptr;
|
||||
@ -3485,14 +3492,14 @@ public:
|
||||
llvm_unreachable("Not Implemented");
|
||||
}
|
||||
|
||||
/// Return 1 if we can compute the negated form of the 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. Else return 0.
|
||||
virtual char isNegatibleForFree(SDValue Op, SelectionDAG &DAG,
|
||||
bool LegalOperations, bool ForCodeSize,
|
||||
unsigned Depth = 0) const;
|
||||
/// Returns whether computing the negated form of the specified expression is
|
||||
/// more expensive, the same cost or cheaper.
|
||||
virtual NegatibleCost getNegatibleCost(SDValue Op, SelectionDAG &DAG,
|
||||
bool LegalOperations, bool ForCodeSize,
|
||||
unsigned Depth = 0) const;
|
||||
|
||||
/// If isNegatibleForFree returns true, return the newly negated expression.
|
||||
/// If getNegatibleCost returns Neutral/Cheaper, return the newly negated
|
||||
/// expression.
|
||||
virtual SDValue getNegatedExpression(SDValue Op, SelectionDAG &DAG,
|
||||
bool LegalOperations, bool ForCodeSize,
|
||||
unsigned Depth = 0) const;
|
||||
|
@ -12165,14 +12165,16 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {
|
||||
|
||||
// fold (fadd A, (fneg B)) -> (fsub A, B)
|
||||
if ((!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FSUB, VT)) &&
|
||||
TLI.isNegatibleForFree(N1, DAG, LegalOperations, ForCodeSize) == 2)
|
||||
TLI.getNegatibleCost(N1, DAG, LegalOperations, ForCodeSize) ==
|
||||
TargetLowering::NegatibleCost::Cheaper)
|
||||
return DAG.getNode(
|
||||
ISD::FSUB, DL, VT, N0,
|
||||
TLI.getNegatedExpression(N1, DAG, LegalOperations, ForCodeSize), Flags);
|
||||
|
||||
// fold (fadd (fneg A), B) -> (fsub B, A)
|
||||
if ((!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FSUB, VT)) &&
|
||||
TLI.isNegatibleForFree(N0, DAG, LegalOperations, ForCodeSize) == 2)
|
||||
TLI.getNegatibleCost(N0, DAG, LegalOperations, ForCodeSize) ==
|
||||
TargetLowering::NegatibleCost::Cheaper)
|
||||
return DAG.getNode(
|
||||
ISD::FSUB, DL, VT, N1,
|
||||
TLI.getNegatedExpression(N0, DAG, LegalOperations, ForCodeSize), Flags);
|
||||
@ -12354,7 +12356,8 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {
|
||||
if (N0CFP && N0CFP->isZero()) {
|
||||
if (N0CFP->isNegative() ||
|
||||
(Options.NoSignedZerosFPMath || Flags.hasNoSignedZeros())) {
|
||||
if (TLI.isNegatibleForFree(N1, DAG, LegalOperations, ForCodeSize))
|
||||
if (TLI.getNegatibleCost(N1, DAG, LegalOperations, ForCodeSize) !=
|
||||
TargetLowering::NegatibleCost::Expensive)
|
||||
return TLI.getNegatedExpression(N1, DAG, LegalOperations, ForCodeSize);
|
||||
if (!LegalOperations || TLI.isOperationLegal(ISD::FNEG, VT))
|
||||
return DAG.getNode(ISD::FNEG, DL, VT, N1, Flags);
|
||||
@ -12373,7 +12376,8 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {
|
||||
}
|
||||
|
||||
// fold (fsub A, (fneg B)) -> (fadd A, B)
|
||||
if (TLI.isNegatibleForFree(N1, DAG, LegalOperations, ForCodeSize))
|
||||
if (TLI.getNegatibleCost(N1, DAG, LegalOperations, ForCodeSize) !=
|
||||
TargetLowering::NegatibleCost::Expensive)
|
||||
return DAG.getNode(
|
||||
ISD::FADD, DL, VT, N0,
|
||||
TLI.getNegatedExpression(N1, DAG, LegalOperations, ForCodeSize), Flags);
|
||||
@ -12390,16 +12394,20 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {
|
||||
/// Return true if both inputs are at least as cheap in negated form and at
|
||||
/// least one input is strictly cheaper in negated form.
|
||||
bool DAGCombiner::isCheaperToUseNegatedFPOps(SDValue X, SDValue Y) {
|
||||
if (char LHSNeg =
|
||||
TLI.isNegatibleForFree(X, DAG, LegalOperations, ForCodeSize))
|
||||
if (char RHSNeg =
|
||||
TLI.isNegatibleForFree(Y, DAG, LegalOperations, ForCodeSize))
|
||||
// Both negated operands are at least as cheap as their counterparts.
|
||||
// Check to see if at least one is cheaper negated.
|
||||
if (LHSNeg == 2 || RHSNeg == 2)
|
||||
return true;
|
||||
TargetLowering::NegatibleCost LHSNeg =
|
||||
TLI.getNegatibleCost(X, DAG, LegalOperations, ForCodeSize);
|
||||
if (TargetLowering::NegatibleCost::Expensive == LHSNeg)
|
||||
return false;
|
||||
|
||||
return false;
|
||||
TargetLowering::NegatibleCost RHSNeg =
|
||||
TLI.getNegatibleCost(Y, DAG, LegalOperations, ForCodeSize);
|
||||
if (TargetLowering::NegatibleCost::Expensive == RHSNeg)
|
||||
return false;
|
||||
|
||||
// Both negated operands are at least as cheap as their counterparts.
|
||||
// Check to see if at least one is cheaper negated.
|
||||
return (TargetLowering::NegatibleCost::Cheaper == LHSNeg ||
|
||||
TargetLowering::NegatibleCost::Cheaper == RHSNeg);
|
||||
}
|
||||
|
||||
SDValue DAGCombiner::visitFMUL(SDNode *N) {
|
||||
@ -12651,8 +12659,8 @@ SDValue DAGCombiner::visitFMA(SDNode *N) {
|
||||
// fold ((fma (fneg X), Y, (fneg Z)) -> fneg (fma X, Y, Z))
|
||||
// fold ((fma X, (fneg Y), (fneg Z)) -> fneg (fma X, Y, Z))
|
||||
if (!TLI.isFNegFree(VT) &&
|
||||
TLI.isNegatibleForFree(SDValue(N, 0), DAG, LegalOperations,
|
||||
ForCodeSize) == 2)
|
||||
TLI.getNegatibleCost(SDValue(N, 0), DAG, LegalOperations, ForCodeSize) ==
|
||||
TargetLowering::NegatibleCost::Cheaper)
|
||||
return DAG.getNode(ISD::FNEG, DL, VT,
|
||||
TLI.getNegatedExpression(SDValue(N, 0), DAG,
|
||||
LegalOperations, ForCodeSize),
|
||||
@ -13387,11 +13395,12 @@ SDValue DAGCombiner::visitFNEG(SDNode *N) {
|
||||
if (isConstantFPBuildVectorOrConstantFP(N0))
|
||||
return DAG.getNode(ISD::FNEG, SDLoc(N), VT, N0);
|
||||
|
||||
if (TLI.isNegatibleForFree(N0, DAG, LegalOperations, ForCodeSize))
|
||||
if (TLI.getNegatibleCost(N0, DAG, LegalOperations, ForCodeSize) !=
|
||||
TargetLowering::NegatibleCost::Expensive)
|
||||
return TLI.getNegatedExpression(N0, DAG, LegalOperations, ForCodeSize);
|
||||
|
||||
// -(X-Y) -> (Y-X) is unsafe because when X==Y, -0.0 != +0.0 FIXME: This is
|
||||
// duplicated in isNegatibleForFree, but isNegatibleForFree doesn't know it
|
||||
// duplicated in getNegatibleCost, but getNegatibleCost doesn't know it
|
||||
// was called from a context with a nsz flag if the input fsub does not.
|
||||
if (N0.getOpcode() == ISD::FSUB &&
|
||||
(DAG.getTarget().Options.NoSignedZerosFPMath ||
|
||||
|
@ -5545,12 +5545,13 @@ verifyReturnAddressArgumentIsConstant(SDValue Op, SelectionDAG &DAG) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
char TargetLowering::isNegatibleForFree(SDValue Op, SelectionDAG &DAG,
|
||||
bool LegalOperations, bool ForCodeSize,
|
||||
unsigned Depth) const {
|
||||
TargetLowering::NegatibleCost
|
||||
TargetLowering::getNegatibleCost(SDValue Op, SelectionDAG &DAG,
|
||||
bool LegalOperations, bool ForCodeSize,
|
||||
unsigned Depth) const {
|
||||
// fneg is removable even if it has multiple uses.
|
||||
if (Op.getOpcode() == ISD::FNEG)
|
||||
return 2;
|
||||
return NegatibleCost::Cheaper;
|
||||
|
||||
// Don't allow anything with multiple uses unless we know it is free.
|
||||
EVT VT = Op.getValueType();
|
||||
@ -5558,107 +5559,115 @@ char TargetLowering::isNegatibleForFree(SDValue Op, SelectionDAG &DAG,
|
||||
const TargetOptions &Options = DAG.getTarget().Options;
|
||||
if (!Op.hasOneUse() && !(Op.getOpcode() == ISD::FP_EXTEND &&
|
||||
isFPExtFree(VT, Op.getOperand(0).getValueType())))
|
||||
return 0;
|
||||
return NegatibleCost::Expensive;
|
||||
|
||||
// Don't recurse exponentially.
|
||||
if (Depth > SelectionDAG::MaxRecursionDepth)
|
||||
return 0;
|
||||
return NegatibleCost::Expensive;
|
||||
|
||||
switch (Op.getOpcode()) {
|
||||
case ISD::ConstantFP: {
|
||||
if (!LegalOperations)
|
||||
return 1;
|
||||
return NegatibleCost::Neutral;
|
||||
|
||||
// Don't invert constant FP values after legalization unless the target says
|
||||
// the negated constant is legal.
|
||||
return isOperationLegal(ISD::ConstantFP, VT) ||
|
||||
isFPImmLegal(neg(cast<ConstantFPSDNode>(Op)->getValueAPF()), VT,
|
||||
ForCodeSize);
|
||||
if (isOperationLegal(ISD::ConstantFP, VT) ||
|
||||
isFPImmLegal(neg(cast<ConstantFPSDNode>(Op)->getValueAPF()), VT,
|
||||
ForCodeSize))
|
||||
return NegatibleCost::Neutral;
|
||||
break;
|
||||
}
|
||||
case ISD::BUILD_VECTOR: {
|
||||
// Only permit BUILD_VECTOR of constants.
|
||||
if (llvm::any_of(Op->op_values(), [&](SDValue N) {
|
||||
return !N.isUndef() && !isa<ConstantFPSDNode>(N);
|
||||
}))
|
||||
return 0;
|
||||
return NegatibleCost::Expensive;
|
||||
if (!LegalOperations)
|
||||
return 1;
|
||||
return NegatibleCost::Neutral;
|
||||
if (isOperationLegal(ISD::ConstantFP, VT) &&
|
||||
isOperationLegal(ISD::BUILD_VECTOR, VT))
|
||||
return 1;
|
||||
return llvm::all_of(Op->op_values(), [&](SDValue N) {
|
||||
return N.isUndef() ||
|
||||
isFPImmLegal(neg(cast<ConstantFPSDNode>(N)->getValueAPF()), VT,
|
||||
ForCodeSize);
|
||||
});
|
||||
return NegatibleCost::Neutral;
|
||||
if (llvm::all_of(Op->op_values(), [&](SDValue N) {
|
||||
return N.isUndef() ||
|
||||
isFPImmLegal(neg(cast<ConstantFPSDNode>(N)->getValueAPF()), VT,
|
||||
ForCodeSize);
|
||||
}))
|
||||
return NegatibleCost::Neutral;
|
||||
break;
|
||||
}
|
||||
case ISD::FADD:
|
||||
case ISD::FADD: {
|
||||
if (!Options.NoSignedZerosFPMath && !Flags.hasNoSignedZeros())
|
||||
return 0;
|
||||
return NegatibleCost::Expensive;
|
||||
|
||||
// After operation legalization, it might not be legal to create new FSUBs.
|
||||
if (LegalOperations && !isOperationLegalOrCustom(ISD::FSUB, VT))
|
||||
return 0;
|
||||
return NegatibleCost::Expensive;
|
||||
|
||||
// fold (fneg (fadd A, B)) -> (fsub (fneg A), B)
|
||||
if (char V = isNegatibleForFree(Op.getOperand(0), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1))
|
||||
return V;
|
||||
NegatibleCost V0 = getNegatibleCost(Op.getOperand(0), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
if (V0 != NegatibleCost::Expensive)
|
||||
return V0;
|
||||
// fold (fneg (fadd A, B)) -> (fsub (fneg B), A)
|
||||
return isNegatibleForFree(Op.getOperand(1), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
return getNegatibleCost(Op.getOperand(1), DAG, LegalOperations, ForCodeSize,
|
||||
Depth + 1);
|
||||
}
|
||||
case ISD::FSUB:
|
||||
// We can't turn -(A-B) into B-A when we honor signed zeros.
|
||||
if (!Options.NoSignedZerosFPMath && !Flags.hasNoSignedZeros())
|
||||
return 0;
|
||||
return NegatibleCost::Expensive;
|
||||
|
||||
// fold (fneg (fsub A, B)) -> (fsub B, A)
|
||||
return 1;
|
||||
|
||||
return NegatibleCost::Neutral;
|
||||
case ISD::FMUL:
|
||||
case ISD::FDIV:
|
||||
case ISD::FDIV: {
|
||||
// fold (fneg (fmul X, Y)) -> (fmul (fneg X), Y) or (fmul X, (fneg Y))
|
||||
if (char V = isNegatibleForFree(Op.getOperand(0), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1))
|
||||
return V;
|
||||
NegatibleCost V0 = getNegatibleCost(Op.getOperand(0), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
if (V0 != NegatibleCost::Expensive)
|
||||
return V0;
|
||||
|
||||
// Ignore X * 2.0 because that is expected to be canonicalized to X + X.
|
||||
if (auto *C = isConstOrConstSplatFP(Op.getOperand(1)))
|
||||
if (C->isExactlyValue(2.0) && Op.getOpcode() == ISD::FMUL)
|
||||
return 0;
|
||||
|
||||
return isNegatibleForFree(Op.getOperand(1), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
return NegatibleCost::Expensive;
|
||||
|
||||
return getNegatibleCost(Op.getOperand(1), DAG, LegalOperations, ForCodeSize,
|
||||
Depth + 1);
|
||||
}
|
||||
case ISD::FMA:
|
||||
case ISD::FMAD: {
|
||||
if (!Options.NoSignedZerosFPMath && !Flags.hasNoSignedZeros())
|
||||
return 0;
|
||||
return NegatibleCost::Expensive;
|
||||
|
||||
// fold (fneg (fma X, Y, Z)) -> (fma (fneg X), Y, (fneg Z))
|
||||
// fold (fneg (fma X, Y, Z)) -> (fma X, (fneg Y), (fneg Z))
|
||||
char V2 = isNegatibleForFree(Op.getOperand(2), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
if (!V2)
|
||||
return 0;
|
||||
NegatibleCost V2 = getNegatibleCost(Op.getOperand(2), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
if (NegatibleCost::Expensive == V2)
|
||||
return NegatibleCost::Expensive;
|
||||
|
||||
// One of Op0/Op1 must be cheaply negatible, then select the cheapest.
|
||||
char V0 = isNegatibleForFree(Op.getOperand(0), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
char V1 = isNegatibleForFree(Op.getOperand(1), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
char V01 = std::max(V0, V1);
|
||||
return V01 ? std::max(V01, V2) : 0;
|
||||
NegatibleCost V0 = getNegatibleCost(Op.getOperand(0), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
NegatibleCost V1 = getNegatibleCost(Op.getOperand(1), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
NegatibleCost V01 = std::max(V0, V1);
|
||||
if (V01 == NegatibleCost::Expensive)
|
||||
return NegatibleCost::Expensive;
|
||||
return std::max(V01, V2);
|
||||
}
|
||||
|
||||
case ISD::FP_EXTEND:
|
||||
case ISD::FP_ROUND:
|
||||
case ISD::FSIN:
|
||||
return isNegatibleForFree(Op.getOperand(0), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
return getNegatibleCost(Op.getOperand(0), DAG, LegalOperations, ForCodeSize,
|
||||
Depth + 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return NegatibleCost::Expensive;
|
||||
}
|
||||
|
||||
SDValue TargetLowering::getNegatedExpression(SDValue Op, SelectionDAG &DAG,
|
||||
@ -5670,7 +5679,7 @@ SDValue TargetLowering::getNegatedExpression(SDValue Op, SelectionDAG &DAG,
|
||||
return Op.getOperand(0);
|
||||
|
||||
assert(Depth <= SelectionDAG::MaxRecursionDepth &&
|
||||
"getNegatedExpression doesn't match isNegatibleForFree");
|
||||
"getNegatedExpression doesn't match getNegatibleCost");
|
||||
const SDNodeFlags Flags = Op->getFlags();
|
||||
|
||||
switch (Op.getOpcode()) {
|
||||
@ -5692,14 +5701,15 @@ SDValue TargetLowering::getNegatedExpression(SDValue Op, SelectionDAG &DAG,
|
||||
}
|
||||
return DAG.getBuildVector(Op.getValueType(), SDLoc(Op), Ops);
|
||||
}
|
||||
case ISD::FADD:
|
||||
case ISD::FADD: {
|
||||
assert((DAG.getTarget().Options.NoSignedZerosFPMath ||
|
||||
Flags.hasNoSignedZeros()) &&
|
||||
"Expected NSZ fp-flag");
|
||||
|
||||
// fold (fneg (fadd A, B)) -> (fsub (fneg A), B)
|
||||
if (isNegatibleForFree(Op.getOperand(0), DAG, LegalOperations, ForCodeSize,
|
||||
Depth + 1))
|
||||
NegatibleCost V0 = getNegatibleCost(Op.getOperand(0), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
if (V0 != NegatibleCost::Expensive)
|
||||
return DAG.getNode(ISD::FSUB, SDLoc(Op), Op.getValueType(),
|
||||
getNegatedExpression(Op.getOperand(0), DAG,
|
||||
LegalOperations, ForCodeSize,
|
||||
@ -5711,6 +5721,7 @@ SDValue TargetLowering::getNegatedExpression(SDValue Op, SelectionDAG &DAG,
|
||||
LegalOperations, ForCodeSize,
|
||||
Depth + 1),
|
||||
Op.getOperand(0), Flags);
|
||||
}
|
||||
case ISD::FSUB:
|
||||
// fold (fneg (fsub 0, B)) -> B
|
||||
if (ConstantFPSDNode *N0CFP =
|
||||
@ -5723,10 +5734,11 @@ SDValue TargetLowering::getNegatedExpression(SDValue Op, SelectionDAG &DAG,
|
||||
Op.getOperand(1), Op.getOperand(0), Flags);
|
||||
|
||||
case ISD::FMUL:
|
||||
case ISD::FDIV:
|
||||
case ISD::FDIV: {
|
||||
// fold (fneg (fmul X, Y)) -> (fmul (fneg X), Y)
|
||||
if (isNegatibleForFree(Op.getOperand(0), DAG, LegalOperations, ForCodeSize,
|
||||
Depth + 1))
|
||||
NegatibleCost V0 = getNegatibleCost(Op.getOperand(0), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
if (V0 != NegatibleCost::Expensive)
|
||||
return DAG.getNode(Op.getOpcode(), SDLoc(Op), Op.getValueType(),
|
||||
getNegatedExpression(Op.getOperand(0), DAG,
|
||||
LegalOperations, ForCodeSize,
|
||||
@ -5739,7 +5751,7 @@ SDValue TargetLowering::getNegatedExpression(SDValue Op, SelectionDAG &DAG,
|
||||
getNegatedExpression(Op.getOperand(1), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1),
|
||||
Flags);
|
||||
|
||||
}
|
||||
case ISD::FMA:
|
||||
case ISD::FMAD: {
|
||||
assert((DAG.getTarget().Options.NoSignedZerosFPMath ||
|
||||
@ -5749,12 +5761,12 @@ SDValue TargetLowering::getNegatedExpression(SDValue Op, SelectionDAG &DAG,
|
||||
SDValue Neg2 = getNegatedExpression(Op.getOperand(2), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
|
||||
char V0 = isNegatibleForFree(Op.getOperand(0), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
char V1 = isNegatibleForFree(Op.getOperand(1), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
NegatibleCost V0 = getNegatibleCost(Op.getOperand(0), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
NegatibleCost V1 = getNegatibleCost(Op.getOperand(1), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
// TODO: This is a hack. It is possible that costs have changed between now
|
||||
// and the initial calls to isNegatibleForFree(). That is because we
|
||||
// and the initial calls to getNegatibleCost(). That is because we
|
||||
// are rewriting the expression, and that may change the number of
|
||||
// uses (and therefore the cost) of values. If the negation costs are
|
||||
// equal, only negate this value if it is a constant. Otherwise, try
|
||||
|
@ -733,24 +733,24 @@ bool AMDGPUTargetLowering::isSDNodeAlwaysUniform(const SDNode * N) const {
|
||||
}
|
||||
}
|
||||
|
||||
char AMDGPUTargetLowering::isNegatibleForFree(SDValue Op, SelectionDAG &DAG,
|
||||
bool LegalOperations,
|
||||
bool ForCodeSize,
|
||||
unsigned Depth) const {
|
||||
TargetLowering::NegatibleCost
|
||||
AMDGPUTargetLowering::getNegatibleCost(SDValue Op, SelectionDAG &DAG,
|
||||
bool LegalOperations, bool ForCodeSize,
|
||||
unsigned Depth) const {
|
||||
switch (Op.getOpcode()) {
|
||||
case ISD::FMA:
|
||||
case ISD::FMAD: {
|
||||
// Negating a fma is not free if it has users without source mods.
|
||||
if (!allUsesHaveSourceMods(Op.getNode()))
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
case ISD::FMA:
|
||||
case ISD::FMAD: {
|
||||
// Negating a fma is not free if it has users without source mods.
|
||||
if (!allUsesHaveSourceMods(Op.getNode()))
|
||||
return NegatibleCost::Expensive;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TargetLowering::isNegatibleForFree(Op, DAG, LegalOperations,
|
||||
ForCodeSize, Depth);
|
||||
return TargetLowering::getNegatibleCost(Op, DAG, LegalOperations, ForCodeSize,
|
||||
Depth);
|
||||
}
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
@ -172,8 +172,9 @@ public:
|
||||
bool isZExtFree(EVT Src, EVT Dest) const override;
|
||||
bool isZExtFree(SDValue Val, EVT VT2) const override;
|
||||
|
||||
char isNegatibleForFree(SDValue Op, SelectionDAG &DAG, bool LegalOperations,
|
||||
bool ForCodeSize, unsigned Depth) const override;
|
||||
NegatibleCost getNegatibleCost(SDValue Op, SelectionDAG &DAG,
|
||||
bool LegalOperations, bool ForCodeSize,
|
||||
unsigned Depth) const override;
|
||||
|
||||
bool isNarrowingProfitable(EVT VT1, EVT VT2) const override;
|
||||
|
||||
|
@ -43217,17 +43217,17 @@ static SDValue combineFneg(SDNode *N, SelectionDAG &DAG,
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
char X86TargetLowering::isNegatibleForFree(SDValue Op, SelectionDAG &DAG,
|
||||
bool LegalOperations,
|
||||
bool ForCodeSize,
|
||||
unsigned Depth) const {
|
||||
TargetLowering::NegatibleCost
|
||||
X86TargetLowering::getNegatibleCost(SDValue Op, SelectionDAG &DAG,
|
||||
bool LegalOperations, bool ForCodeSize,
|
||||
unsigned Depth) const {
|
||||
// fneg patterns are removable even if they have multiple uses.
|
||||
if (isFNEG(DAG, Op.getNode(), Depth))
|
||||
return 2;
|
||||
return NegatibleCost::Cheaper;
|
||||
|
||||
// Don't recurse exponentially.
|
||||
if (Depth > SelectionDAG::MaxRecursionDepth)
|
||||
return 0;
|
||||
return NegatibleCost::Expensive;
|
||||
|
||||
EVT VT = Op.getValueType();
|
||||
EVT SVT = VT.getScalarType();
|
||||
@ -43248,20 +43248,20 @@ char X86TargetLowering::isNegatibleForFree(SDValue Op, SelectionDAG &DAG,
|
||||
// This is always negatible for free but we might be able to remove some
|
||||
// extra operand negations as well.
|
||||
for (int i = 0; i != 3; ++i) {
|
||||
char V = isNegatibleForFree(Op.getOperand(i), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
if (V == 2)
|
||||
NegatibleCost V = getNegatibleCost(Op.getOperand(i), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
if (V == NegatibleCost::Cheaper)
|
||||
return V;
|
||||
}
|
||||
return 1;
|
||||
return NegatibleCost::Neutral;
|
||||
}
|
||||
case X86ISD::FRCP:
|
||||
return isNegatibleForFree(Op.getOperand(0), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
return getNegatibleCost(Op.getOperand(0), DAG, LegalOperations, ForCodeSize,
|
||||
Depth + 1);
|
||||
}
|
||||
|
||||
return TargetLowering::isNegatibleForFree(Op, DAG, LegalOperations,
|
||||
ForCodeSize, Depth);
|
||||
return TargetLowering::getNegatibleCost(Op, DAG, LegalOperations, ForCodeSize,
|
||||
Depth);
|
||||
}
|
||||
|
||||
SDValue X86TargetLowering::getNegatedExpression(SDValue Op, SelectionDAG &DAG,
|
||||
@ -43293,9 +43293,9 @@ SDValue X86TargetLowering::getNegatedExpression(SDValue Op, SelectionDAG &DAG,
|
||||
// extra operand negations as well.
|
||||
SmallVector<SDValue, 4> NewOps(Op.getNumOperands(), SDValue());
|
||||
for (int i = 0; i != 3; ++i) {
|
||||
char V = isNegatibleForFree(Op.getOperand(i), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
if (V == 2)
|
||||
NegatibleCost V = getNegatibleCost(Op.getOperand(i), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
if (V == NegatibleCost::Cheaper)
|
||||
NewOps[i] = getNegatedExpression(Op.getOperand(i), DAG, LegalOperations,
|
||||
ForCodeSize, Depth + 1);
|
||||
}
|
||||
@ -44154,7 +44154,8 @@ static SDValue combineFMA(SDNode *N, SelectionDAG &DAG,
|
||||
auto invertIfNegative = [&DAG, &TLI, &DCI](SDValue &V) {
|
||||
bool CodeSize = DAG.getMachineFunction().getFunction().hasOptSize();
|
||||
bool LegalOperations = !DCI.isBeforeLegalizeOps();
|
||||
if (TLI.isNegatibleForFree(V, DAG, LegalOperations, CodeSize) == 2) {
|
||||
if (TLI.getNegatibleCost(V, DAG, LegalOperations, CodeSize) ==
|
||||
TargetLowering::NegatibleCost::Cheaper) {
|
||||
V = TLI.getNegatedExpression(V, DAG, LegalOperations, CodeSize);
|
||||
return true;
|
||||
}
|
||||
@ -44163,7 +44164,8 @@ static SDValue combineFMA(SDNode *N, SelectionDAG &DAG,
|
||||
if (V.getOpcode() == ISD::EXTRACT_VECTOR_ELT &&
|
||||
isNullConstant(V.getOperand(1))) {
|
||||
SDValue Vec = V.getOperand(0);
|
||||
if (TLI.isNegatibleForFree(Vec, DAG, LegalOperations, CodeSize) == 2) {
|
||||
if (TLI.getNegatibleCost(Vec, DAG, LegalOperations, CodeSize) ==
|
||||
TargetLowering::NegatibleCost::Cheaper) {
|
||||
SDValue NegVal =
|
||||
TLI.getNegatedExpression(Vec, DAG, LegalOperations, CodeSize);
|
||||
V = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(V), V.getValueType(),
|
||||
@ -44209,7 +44211,8 @@ static SDValue combineFMADDSUB(SDNode *N, SelectionDAG &DAG,
|
||||
bool LegalOperations = !DCI.isBeforeLegalizeOps();
|
||||
|
||||
SDValue N2 = N->getOperand(2);
|
||||
if (TLI.isNegatibleForFree(N2, DAG, LegalOperations, CodeSize) != 2)
|
||||
if (TLI.getNegatibleCost(N2, DAG, LegalOperations, CodeSize) !=
|
||||
TargetLowering::NegatibleCost::Cheaper)
|
||||
return SDValue();
|
||||
|
||||
SDValue NegN2 = TLI.getNegatedExpression(N2, DAG, LegalOperations, CodeSize);
|
||||
|
@ -808,13 +808,14 @@ namespace llvm {
|
||||
/// and some i16 instructions are slow.
|
||||
bool IsDesirableToPromoteOp(SDValue Op, EVT &PVT) const override;
|
||||
|
||||
/// Return 1 if we can compute the negated form of the 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. Else return 0.
|
||||
char isNegatibleForFree(SDValue Op, SelectionDAG &DAG, bool LegalOperations,
|
||||
bool ForCodeSize, unsigned Depth) const override;
|
||||
/// Returns whether computing the negated form of the specified expression
|
||||
/// is more expensive, the same cost or cheaper.
|
||||
NegatibleCost getNegatibleCost(SDValue Op, SelectionDAG &DAG,
|
||||
bool LegalOperations, bool ForCodeSize,
|
||||
unsigned Depth) const override;
|
||||
|
||||
/// If isNegatibleForFree returns true, return the newly negated expression.
|
||||
/// If getNegatibleCost returns Neutral/Cheaper, return the newly negated
|
||||
/// expression.
|
||||
SDValue getNegatedExpression(SDValue Op, SelectionDAG &DAG,
|
||||
bool LegalOperations, bool ForCodeSize,
|
||||
unsigned Depth) const override;
|
||||
|
Loading…
Reference in New Issue
Block a user