Skip to content

Commit 5ec1353

Browse files
committed
[DAGCombiner] Change foldAndOrOfSETCC() to optimize and/or patterns with floating points.
CMP(A,C)||CMP(B,C) => CMP(MIN/MAX(A,B), C) CMP(A,C)&&CMP(B,C) => CMP(MIN/MAX(A,B), C) If the operands are proven to be non NaN, then the optimization can be applied for all predicates. We can apply the optimization for the following predicates for FMINNUM/FMAXNUM (for quiet and signaling NaNs) and for FMINNUM_IEEE/FMAXNUM_IEEE if we can prove that the operands are not signaling NaNs. - ordered lt/le and || - ordered gt/ge and || - unordered lt/le and && - unordered gt/ge and && Reviewed By: arsenm Differential Revision: https://reviews.llvm.org/D155267
1 parent b49bb7b commit 5ec1353

File tree

5 files changed

+2017
-1548
lines changed

5 files changed

+2017
-1548
lines changed

llvm/include/llvm/CodeGen/ISDOpcodes.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,6 +1543,12 @@ inline bool isIntEqualitySetCC(CondCode Code) {
15431543
return Code == SETEQ || Code == SETNE;
15441544
}
15451545

1546+
/// Return true if this is a setcc instruction that performs an equality
1547+
/// comparison when used with floating point operands.
1548+
inline bool isFPEqualitySetCC(CondCode Code) {
1549+
return Code == SETOEQ || Code == SETONE || Code == SETUEQ || Code == SETUNE;
1550+
}
1551+
15461552
/// Return true if the specified condition returns true if the two operands to
15471553
/// the condition are equal. Note that if one of the two operands is a NaN,
15481554
/// this value is meaningless.

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 93 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6042,6 +6042,67 @@ SDValue DAGCombiner::foldLogicOfSetCCs(bool IsAnd, SDValue N0, SDValue N1,
60426042
return SDValue();
60436043
}
60446044

6045+
static bool arebothOperandsNotSNan(SDValue Operand1, SDValue Operand2,
6046+
SelectionDAG &DAG) {
6047+
return DAG.isKnownNeverSNaN(Operand2) && DAG.isKnownNeverSNaN(Operand1);
6048+
}
6049+
6050+
static bool arebothOperandsNotNan(SDValue Operand1, SDValue Operand2,
6051+
SelectionDAG &DAG) {
6052+
return DAG.isKnownNeverNaN(Operand2) && DAG.isKnownNeverNaN(Operand1);
6053+
}
6054+
6055+
static unsigned getMinMaxOpcodeForFP(SDValue Operand1, SDValue Operand2,
6056+
ISD::CondCode CC, unsigned OrAndOpcode,
6057+
SelectionDAG &DAG) {
6058+
// The optimization cannot be applied for all the predicates because
6059+
// of the way FMINNUM/FMAXNUM and FMINNUM_IEEE/FMAXNUM_IEEE handle
6060+
// NaNs. For FMINNUM_IEEE/FMAXNUM_IEEE, the optimization cannot be
6061+
// applied at all if one of the operands is a signaling NaN.
6062+
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
6063+
EVT OpVT = Operand1.getValueType();
6064+
// It is safe to use FMINNUM_IEEE/FMAXNUM_IEEE if all the operands
6065+
// are non NaN values.
6066+
if (((CC == ISD::SETLT || CC == ISD::SETLE) && (OrAndOpcode == ISD::OR)) ||
6067+
((CC == ISD::SETGT || CC == ISD::SETGE) && (OrAndOpcode == ISD::AND)))
6068+
return arebothOperandsNotNan(Operand1, Operand2, DAG) ? ISD::FMINNUM_IEEE
6069+
: ISD::DELETED_NODE;
6070+
else if (((CC == ISD::SETGT || CC == ISD::SETGE) &&
6071+
(OrAndOpcode == ISD::OR)) ||
6072+
((CC == ISD::SETLT || CC == ISD::SETLE) &&
6073+
(OrAndOpcode == ISD::AND)))
6074+
return arebothOperandsNotNan(Operand1, Operand2, DAG) ? ISD::FMAXNUM_IEEE
6075+
: ISD::DELETED_NODE;
6076+
// Both FMINNUM/FMAXNUM and FMINNUM_IEEE/FMAXNUM_IEEE handle quiet
6077+
// NaNs in the same way. But, FMINNUM/FMAXNUM and FMINNUM_IEEE/
6078+
// FMAXNUM_IEEE handle signaling NaNs differently. If we cannot prove
6079+
// that there are not any sNaNs, then the optimization is not valid
6080+
// for FMINNUM_IEEE/FMAXNUM_IEEE. In the presence of sNaNs, we apply
6081+
// the optimization using FMINNUM/FMAXNUM for the following cases. If
6082+
// we can prove that we do not have any sNaNs, then we can do the
6083+
// optimization using FMINNUM_IEEE/FMAXNUM_IEEE for the following
6084+
// cases.
6085+
else if (((CC == ISD::SETOLT || CC == ISD::SETOLE) &&
6086+
(OrAndOpcode == ISD::OR)) ||
6087+
((CC == ISD::SETUGT || CC == ISD::SETUGE) &&
6088+
(OrAndOpcode == ISD::AND)))
6089+
return TLI.isOperationLegalOrCustom(ISD::FMINNUM, OpVT)
6090+
? ISD::FMINNUM
6091+
: arebothOperandsNotSNan(Operand1, Operand2, DAG)
6092+
? ISD::FMINNUM_IEEE
6093+
: ISD::DELETED_NODE;
6094+
else if (((CC == ISD::SETOGT || CC == ISD::SETOGE) &&
6095+
(OrAndOpcode == ISD::OR)) ||
6096+
((CC == ISD::SETULT || CC == ISD::SETULE) &&
6097+
(OrAndOpcode == ISD::AND)))
6098+
return TLI.isOperationLegalOrCustom(ISD::FMAXNUM, OpVT)
6099+
? ISD::FMAXNUM
6100+
: arebothOperandsNotSNan(Operand1, Operand2, DAG)
6101+
? ISD::FMAXNUM_IEEE
6102+
: ISD::DELETED_NODE;
6103+
return ISD::DELETED_NODE;
6104+
}
6105+
60456106
static SDValue foldAndOrOfSETCC(SDNode *LogicOp, SelectionDAG &DAG) {
60466107
using AndOrSETCCFoldKind = TargetLowering::AndOrSETCCFoldKind;
60476108
assert(
@@ -6083,12 +6144,20 @@ static SDValue foldAndOrOfSETCC(SDNode *LogicOp, SelectionDAG &DAG) {
60836144
// The optimization does not work for `==` or `!=` .
60846145
// The two comparisons should have either the same predicate or the
60856146
// predicate of one of the comparisons is the opposite of the other one.
6086-
if (OpVT.isInteger() && !ISD::isIntEqualitySetCC(CCL) &&
6087-
(CCL == CCR || CCL == ISD::getSetCCSwappedOperands(CCR)) &&
6088-
TLI.isOperationLegal(ISD::UMAX, OpVT) &&
6089-
TLI.isOperationLegal(ISD::SMAX, OpVT) &&
6090-
TLI.isOperationLegal(ISD::UMIN, OpVT) &&
6091-
TLI.isOperationLegal(ISD::SMIN, OpVT)) {
6147+
if (((OpVT.isInteger() && TLI.isOperationLegal(ISD::UMAX, OpVT) &&
6148+
TLI.isOperationLegal(ISD::SMAX, OpVT) &&
6149+
TLI.isOperationLegal(ISD::UMIN, OpVT) &&
6150+
TLI.isOperationLegal(ISD::SMIN, OpVT)) ||
6151+
(OpVT.isFloatingPoint() &&
6152+
((TLI.isOperationLegalOrCustom(ISD::FMAXNUM, OpVT) &&
6153+
TLI.isOperationLegalOrCustom(ISD::FMINNUM, OpVT)) ||
6154+
(TLI.isOperationLegal(ISD::FMAXNUM_IEEE, OpVT) &&
6155+
TLI.isOperationLegal(ISD::FMINNUM_IEEE, OpVT))))) &&
6156+
!ISD::isIntEqualitySetCC(CCL) && !ISD::isFPEqualitySetCC(CCL) &&
6157+
CCL != ISD::SETFALSE && CCL != ISD::SETO && CCL != ISD::SETUO &&
6158+
CCL != ISD::SETTRUE &&
6159+
(CCL == CCR || CCL == ISD::getSetCCSwappedOperands(CCR))) {
6160+
60926161
SDValue CommonValue, Operand1, Operand2;
60936162
ISD::CondCode CC = ISD::SETCC_INVALID;
60946163
if (CCL == CCR) {
@@ -6126,19 +6195,25 @@ static SDValue foldAndOrOfSETCC(SDNode *LogicOp, SelectionDAG &DAG) {
61266195
CC = ISD::SETCC_INVALID;
61276196

61286197
if (CC != ISD::SETCC_INVALID) {
6129-
unsigned NewOpcode;
6198+
unsigned NewOpcode = ISD::DELETED_NODE;
61306199
bool IsSigned = isSignedIntSetCC(CC);
6131-
bool IsLess = (CC == ISD::SETLE || CC == ISD::SETULE ||
6132-
CC == ISD::SETLT || CC == ISD::SETULT);
6133-
bool IsOr = (LogicOp->getOpcode() == ISD::OR);
6134-
if (IsLess == IsOr)
6135-
NewOpcode = IsSigned ? ISD::SMIN : ISD::UMIN;
6136-
else
6137-
NewOpcode = IsSigned ? ISD::SMAX : ISD::UMAX;
6138-
6139-
SDValue MinMaxValue =
6140-
DAG.getNode(NewOpcode, DL, OpVT, Operand1, Operand2);
6141-
return DAG.getSetCC(DL, VT, MinMaxValue, CommonValue, CC);
6200+
if (OpVT.isInteger()) {
6201+
bool IsLess = (CC == ISD::SETLE || CC == ISD::SETULE ||
6202+
CC == ISD::SETLT || CC == ISD::SETULT);
6203+
bool IsOr = (LogicOp->getOpcode() == ISD::OR);
6204+
if (IsLess == IsOr)
6205+
NewOpcode = IsSigned ? ISD::SMIN : ISD::UMIN;
6206+
else
6207+
NewOpcode = IsSigned ? ISD::SMAX : ISD::UMAX;
6208+
} else if (OpVT.isFloatingPoint())
6209+
NewOpcode = getMinMaxOpcodeForFP(Operand1, Operand2, CC,
6210+
LogicOp->getOpcode(), DAG);
6211+
6212+
if (NewOpcode != ISD::DELETED_NODE) {
6213+
SDValue MinMaxValue =
6214+
DAG.getNode(NewOpcode, DL, OpVT, Operand1, Operand2);
6215+
return DAG.getSetCC(DL, VT, MinMaxValue, CommonValue, CC);
6216+
}
61426217
}
61436218
}
61446219

0 commit comments

Comments
 (0)