[llvm] Intrinsic: introduce minimumnum and maximumnum for IR and SelectionDAG (PR #96649)
Thorsten Schütt via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 10 03:35:18 PDT 2024
================
@@ -8531,6 +8531,108 @@ SDValue TargetLowering::expandFMINIMUM_FMAXIMUM(SDNode *N,
return MinMax;
}
+SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
+ SelectionDAG &DAG) const {
+ SDLoc DL(Node);
+ SDValue LHS = Node->getOperand(0);
+ SDValue RHS = Node->getOperand(1);
+ unsigned Opc = Node->getOpcode();
+ EVT VT = Node->getValueType(0);
+ EVT CCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
+ bool IsMax = Opc == ISD::FMAXIMUMNUM;
+ const TargetOptions &Options = DAG.getTarget().Options;
+ SDNodeFlags Flags = Node->getFlags();
+
+ unsigned NewOp =
+ Opc == ISD::FMINIMUMNUM ? ISD::FMINNUM_IEEE : ISD::FMAXNUM_IEEE;
+
+ if (isOperationLegalOrCustom(NewOp, VT)) {
+ if (!Flags.hasNoNaNs()) {
+ // Insert canonicalizes if it's possible we need to quiet to get correct
+ // sNaN behavior.
+ if (!DAG.isKnownNeverSNaN(LHS)) {
+ LHS = DAG.getNode(ISD::FCANONICALIZE, DL, VT, LHS, Flags);
+ }
+ if (!DAG.isKnownNeverSNaN(RHS)) {
+ RHS = DAG.getNode(ISD::FCANONICALIZE, DL, VT, RHS, Flags);
+ }
+ }
+
+ return DAG.getNode(NewOp, DL, VT, LHS, RHS, Flags);
+ }
+
+ // We can use FMINIMUM/FMAXIMUM if there is no NaN, since it has
+ // same behaviors for all of other cases: +0.0 vs -0.0 included.
+ if (Flags.hasNoNaNs() ||
+ (DAG.isKnownNeverNaN(LHS) && DAG.isKnownNeverNaN(RHS))) {
+ unsigned IEEE2019Op =
+ Opc == ISD::FMINIMUMNUM ? ISD::FMINIMUM : ISD::FMAXIMUM;
+ if (isOperationLegalOrCustom(IEEE2019Op, VT))
+ return DAG.getNode(IEEE2019Op, DL, VT, LHS, RHS, Flags);
+ }
+
+ // FMINNUM/FMAXMUM returns qNaN if either operand is sNaN, and it may return
+ // either one for +0.0 vs -0.0.
+ if ((Flags.hasNoNaNs() ||
+ (DAG.isKnownNeverSNaN(LHS) && DAG.isKnownNeverSNaN(RHS))) &&
+ (Flags.hasNoSignedZeros() || DAG.isKnownNeverZeroFloat(LHS) ||
+ DAG.isKnownNeverZeroFloat(RHS))) {
+ unsigned IEEE2008Op = Opc == ISD::FMINIMUMNUM ? ISD::FMINNUM : ISD::FMAXNUM;
+ if (isOperationLegalOrCustom(IEEE2008Op, VT))
+ return DAG.getNode(IEEE2008Op, DL, VT, LHS, RHS, Flags);
+ }
+
+ // If only one operand is NaN, override it with another operand.
+ if (!Flags.hasNoNaNs() && !DAG.isKnownNeverNaN(LHS)) {
+ LHS = DAG.getSelectCC(DL, LHS, LHS, RHS, LHS, ISD::SETUO);
+ }
+ if (!Flags.hasNoNaNs() && !DAG.isKnownNeverNaN(RHS)) {
+ RHS = DAG.getSelectCC(DL, RHS, RHS, LHS, RHS, ISD::SETUO);
+ }
+
+ SDValue MinMax =
+ DAG.getSelectCC(DL, LHS, RHS, LHS, RHS, IsMax ? ISD::SETGT : ISD::SETLT);
+ // If MinMax is NaN, let's quiet it.
+ if (!Flags.hasNoNaNs() && !DAG.isKnownNeverNaN(LHS) &&
+ !DAG.isKnownNeverNaN(RHS)) {
+ // Only use FADD to quiet it if it is NaN, because -0.0+0.0->+0.0.
+ SDValue MinMaxQuiet = DAG.getNode(ISD::FADD, DL, VT, MinMax, MinMax, Flags);
+ MinMax =
+ DAG.getSelectCC(DL, MinMax, MinMax, MinMaxQuiet, MinMax, ISD::SETUO);
+ }
+
+ // Fixup signed zero behavior.
+ if (Options.NoSignedZerosFPMath || Flags.hasNoSignedZeros() ||
+ DAG.isKnownNeverZeroFloat(LHS) || DAG.isKnownNeverZeroFloat(RHS)) {
+ return MinMax;
+ } else {
----------------
tschuett wrote:
It is forbidden:
https://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return
https://github.com/llvm/llvm-project/pull/96649
More information about the llvm-commits
mailing list