[clang] [llvm] Intrinsic: introduce minimumnum and maximumnum (PR #93841)

via cfe-commits cfe-commits at lists.llvm.org
Thu May 30 09:23:09 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-llvm-selectiondag

Author: YunQiang Su (wzssyqa)

<details>
<summary>Changes</summary>

Currently, on different platform, the behaivor of llvm.minnum is different if one operand is sNaN:

When we compare sNaN vs NUM:

ARM/AArch64/PowerPC: follow the IEEE754-2008's minNUM: return qNaN. RISC-V/Hexagon follow the IEEE754-2019's minimumNumber: return NUM. X86: Returns NUM but not same with IEEE754-2019's minimumNumber as
     +0.0 is not always greater than -0.0.
MIPS/LoongArch/Generic: return NUM.
LIBCALL: returns qNaN.

So, let's introduce llvm.minmumnum/llvm.maximumnum, which always follow IEEE754-2019's minimumNumber/maximumNumber.

Half-fix: #<!-- -->93033

---

Patch is 170.43 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/93841.diff


78 Files Affected:

- (modified) clang/include/clang/Basic/Builtins.td (+28) 
- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+24) 
- (modified) clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc (+6) 
- (modified) clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc (+18) 
- (modified) clang/test/CodeGen/builtins.c (+18) 
- (modified) clang/test/CodeGen/math-libcalls.c (+25) 
- (modified) llvm/docs/LangRef.rst (+78) 
- (modified) llvm/include/llvm/ADT/APFloat.h (+20) 
- (modified) llvm/include/llvm/Analysis/IVDescriptors.h (+25-22) 
- (modified) llvm/include/llvm/Analysis/TargetLibraryInfo.def (+33) 
- (modified) llvm/include/llvm/Analysis/ValueTracking.h (+10-8) 
- (modified) llvm/include/llvm/CodeGen/BasicTTIImpl.h (+10) 
- (modified) llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h (+2) 
- (modified) llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h (+12) 
- (modified) llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h (+1) 
- (modified) llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h (+24) 
- (modified) llvm/include/llvm/CodeGen/GlobalISel/Utils.h (+4) 
- (modified) llvm/include/llvm/CodeGen/ISDOpcodes.h (+11) 
- (modified) llvm/include/llvm/CodeGen/TargetLowering.h (+7) 
- (modified) llvm/include/llvm/IR/ConstrainedOps.def (+2) 
- (modified) llvm/include/llvm/IR/IRBuilder.h (+12) 
- (modified) llvm/include/llvm/IR/IntrinsicInst.h (+2) 
- (modified) llvm/include/llvm/IR/Intrinsics.td (+40) 
- (modified) llvm/include/llvm/IR/RuntimeLibcalls.def (+10) 
- (modified) llvm/include/llvm/IR/VPIntrinsics.def (+22) 
- (modified) llvm/include/llvm/Support/TargetOpcodes.def (+6) 
- (modified) llvm/include/llvm/Target/GenericOpcodes.td (+19) 
- (modified) llvm/include/llvm/Target/GlobalISel/Combine.td (+3-3) 
- (modified) llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td (+4) 
- (modified) llvm/include/llvm/Target/TargetSelectionDAG.td (+18) 
- (modified) llvm/lib/Analysis/ConstantFolding.cpp (+8) 
- (modified) llvm/lib/Analysis/IVDescriptors.cpp (+4) 
- (modified) llvm/lib/Analysis/InstructionSimplify.cpp (+16-2) 
- (modified) llvm/lib/Analysis/ValueTracking.cpp (+24-7) 
- (modified) llvm/lib/Analysis/VectorUtils.cpp (+2) 
- (modified) llvm/lib/CodeGen/ExpandVectorPredication.cpp (+17-1) 
- (modified) llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp (+2) 
- (modified) llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp (+2) 
- (modified) llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp (+8) 
- (modified) llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp (+51-2) 
- (modified) llvm/lib/CodeGen/GlobalISel/Utils.cpp (+9-1) 
- (modified) llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (+9-3) 
- (modified) llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp (+32) 
- (modified) llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp (+61-1) 
- (modified) llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h (+4) 
- (modified) llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp (+13) 
- (modified) llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp (+14) 
- (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (+15-3) 
- (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (+27) 
- (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp (+8) 
- (modified) llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp (+101-5) 
- (modified) llvm/lib/CodeGen/TargetLoweringBase.cpp (+1) 
- (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (+3) 
- (modified) llvm/lib/Target/AArch64/AArch64InstrInfo.td (+12) 
- (modified) llvm/lib/Target/Hexagon/HexagonISelLowering.cpp (+5) 
- (modified) llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp (+6) 
- (modified) llvm/lib/Target/Hexagon/HexagonPatterns.td (+4) 
- (modified) llvm/lib/Target/Hexagon/HexagonPatternsHVX.td (+8) 
- (modified) llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp (+3-1) 
- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+25-7) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoD.td (+2) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoF.td (+2) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td (+2) 
- (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+4) 
- (modified) llvm/lib/Target/X86/X86TargetTransformInfo.cpp (+12-4) 
- (modified) llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp (+4) 
- (modified) llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir (+12) 
- (added) llvm/test/CodeGen/AArch64/fp-maximumnum-minimumnum.ll (+51) 
- (modified) llvm/test/CodeGen/Hexagon/fminmax-v67.ll (+40) 
- (added) llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll (+154) 
- (added) llvm/test/CodeGen/Mips/fp-maximumnum-minimumnum.ll (+100) 
- (modified) llvm/test/CodeGen/RISCV/double-intrinsics.ll (+128-50) 
- (modified) llvm/test/CodeGen/RISCV/float-intrinsics.ll (+136-48) 
- (modified) llvm/test/TableGen/GlobalISelEmitter.td (+1-1) 
- (modified) llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml (+10-4) 
- (modified) llvm/unittests/ADT/APFloatTest.cpp (+40) 
- (modified) llvm/unittests/Analysis/TargetLibraryInfoTest.cpp (+7-1) 
- (modified) llvm/unittests/IR/VPIntrinsicTest.cpp (+4-2) 


``````````diff
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 11982af3fa609..b2d1ab2a8be8d 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -215,6 +215,18 @@ def FminF16F128 : Builtin, F16F128MathTemplate {
   let Prototype = "T(T, T)";
 }
 
+def FmaximumNumF16F128 : Builtin, F16F128MathTemplate {
+  let Spellings = ["__builtin_fmaximum_num"];
+  let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const, Constexpr];
+  let Prototype = "T(T, T)";
+}
+
+def FminimumNumF16F128 : Builtin, F16F128MathTemplate {
+  let Spellings = ["__builtin_fminimum_num"];
+  let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const, Constexpr];
+  let Prototype = "T(T, T)";
+}
+
 def Atan2F128 : Builtin {
   let Spellings = ["__builtin_atan2f128"];
   let Attributes = [FunctionWithBuiltinPrefix, NoThrow, ConstIgnoringErrnoAndExceptions];
@@ -3636,6 +3648,22 @@ def Fmin : FPMathTemplate, LibBuiltin<"math.h"> {
   let OnlyBuiltinPrefixedAliasIsConstexpr = 1;
 }
 
+def FmaximumNum : FPMathTemplate, LibBuiltin<"math.h"> {
+  let Spellings = ["fmaximum_num"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "T(T, T)";
+  let AddBuiltinPrefixedAlias = 1;
+  let OnlyBuiltinPrefixedAliasIsConstexpr = 1;
+}
+
+def FminimumNum : FPMathTemplate, LibBuiltin<"math.h"> {
+  let Spellings = ["fminimum_num"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "T(T, T)";
+  let AddBuiltinPrefixedAlias = 1;
+  let OnlyBuiltinPrefixedAliasIsConstexpr = 1;
+}
+
 def Hypot : FPMathTemplate, LibBuiltin<"math.h"> {
   let Spellings = ["hypot"];
   let Attributes = [NoThrow, ConstIgnoringErrnoAndExceptions];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 266bf41fd5577..f2a15dc9cf3d6 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -2786,6 +2786,30 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
                                    Intrinsic::minnum,
                                    Intrinsic::experimental_constrained_minnum));
 
+    case Builtin::BIfmaximum_num:
+    case Builtin::BIfmaximum_numf:
+    case Builtin::BIfmaximum_numl:
+    case Builtin::BI__builtin_fmaximum_num:
+    case Builtin::BI__builtin_fmaximum_numf:
+    case Builtin::BI__builtin_fmaximum_numf16:
+    case Builtin::BI__builtin_fmaximum_numl:
+    case Builtin::BI__builtin_fmaximum_numf128:
+      return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(*this, E,
+                                   Intrinsic::maximumnum,
+                                   Intrinsic::experimental_constrained_maximumnum));
+
+    case Builtin::BIfminimum_num:
+    case Builtin::BIfminimum_numf:
+    case Builtin::BIfminimum_numl:
+    case Builtin::BI__builtin_fminimum_num:
+    case Builtin::BI__builtin_fminimum_numf:
+    case Builtin::BI__builtin_fminimum_numf16:
+    case Builtin::BI__builtin_fminimum_numl:
+    case Builtin::BI__builtin_fminimum_numf128:
+      return RValue::get(emitBinaryMaybeConstrainedFPBuiltin(*this, E,
+                                   Intrinsic::minnum,
+                                   Intrinsic::experimental_constrained_minimumnum));
+
     // fmod() is a special-case. It maps to the frem instruction rather than an
     // LLVM intrinsic.
     case Builtin::BIfmod:
diff --git a/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc b/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc
index 463ce921f0672..af2dcb632fbb6 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc
+++ b/clang/lib/Tooling/Inclusions/Stdlib/CSymbolMap.inc
@@ -475,6 +475,12 @@ SYMBOL(fmaxl, None, <math.h>)
 SYMBOL(fmin, None, <math.h>)
 SYMBOL(fminf, None, <math.h>)
 SYMBOL(fminl, None, <math.h>)
+SYMBOL(fmaximum_num, None, <math.h>)
+SYMBOL(fmaximum_numf, None, <math.h>)
+SYMBOL(fmaximum_numfl, None, <math.h>)
+SYMBOL(fminimum_num, None, <math.h>)
+SYMBOL(fminimum_numf, None, <math.h>)
+SYMBOL(fminimum_numl, None, <math.h>)
 SYMBOL(fmod, None, <math.h>)
 SYMBOL(fmodf, None, <math.h>)
 SYMBOL(fmodl, None, <math.h>)
diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc b/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
index b46bd2e4d7a4b..442316ce8d4ff 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
@@ -1295,6 +1295,24 @@ SYMBOL(fminf, None, <math.h>)
 SYMBOL(fminl, std::, <cmath>)
 SYMBOL(fminl, None, <cmath>)
 SYMBOL(fminl, None, <math.h>)
+SYMBOL(fmaximum_num, std::, <cmath>)
+SYMBOL(fmaximum_num, None, <cmath>)
+SYMBOL(fmaximum_num, None, <math.h>)
+SYMBOL(fmaximum_numf, std::, <cmath>)
+SYMBOL(fmaximum_numf, None, <cmath>)
+SYMBOL(fmaximum_numf, None, <math.h>)
+SYMBOL(fmaximum_numl, std::, <cmath>)
+SYMBOL(fmaximum_numl, None, <cmath>)
+SYMBOL(fmaximum_numl, None, <math.h>)
+SYMBOL(fminimum_num, std::, <cmath>)
+SYMBOL(fminimum_num, None, <cmath>)
+SYMBOL(fminimum_num, None, <math.h>)
+SYMBOL(fminimum_numf, std::, <cmath>)
+SYMBOL(fminimum_numf, None, <cmath>)
+SYMBOL(fminimum_numf, None, <math.h>)
+SYMBOL(fminimum_numl, std::, <cmath>)
+SYMBOL(fminimum_numl, None, <cmath>)
+SYMBOL(fminimum_numl, None, <math.h>)
 SYMBOL(fmod, std::, <cmath>)
 SYMBOL(fmod, None, <cmath>)
 SYMBOL(fmod, None, <math.h>)
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index b41efb59e61db..b059346bf93d3 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -353,6 +353,24 @@ void test_float_builtin_ops(float F, double D, long double LD) {
   resld = __builtin_fmaxl(LD, LD);
   // CHECK: call x86_fp80 @llvm.maxnum.f80
 
+  resf = __builtin_fminimum_numf(F, F);
+  // CHECK: call float @llvm.minimumnum.f32
+
+  resd = __builtin_fminimum_num(D, D);
+  // CHECK: call double @llvm.minimumnum.f64
+
+  resld = __builtin_fminimum_numl(LD, LD);
+  // CHECK: call x86_fp80 @llvm.minimumnum.f80
+
+  resf = __builtin_fmaximum_numf(F, F);
+  // CHECK: call float @llvm.maximumnum.f32
+
+  resd = __builtin_fmaximum_num(D, D);
+  // CHECK: call double @llvm.maximumnum.f64
+
+  resld = __builtin_fmaximum_numl(LD, LD);
+  // CHECK: call x86_fp80 @llvm.maximumnum.f80
+
   resf = __builtin_fabsf(F);
   // CHECK: call float @llvm.fabs.f32
 
diff --git a/clang/test/CodeGen/math-libcalls.c b/clang/test/CodeGen/math-libcalls.c
index 29c312ba0ecac..caf9d060fc525 100644
--- a/clang/test/CodeGen/math-libcalls.c
+++ b/clang/test/CodeGen/math-libcalls.c
@@ -372,6 +372,31 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
 // HAS_MAYTRAP: declare float @llvm.experimental.constrained.minnum.f32(
 // HAS_MAYTRAP: declare x86_fp80 @llvm.experimental.constrained.minnum.f80(
 
+  fmaximum_num(f,f);       fmaximum_numf(f,f);      fmaximum_numl(f,f);
+
+// NO__ERRNO: declare double @llvm.maximumnum.f64(double, double) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare float @llvm.maximumnum.f32(float, float) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare x86_fp80 @llvm.maximumnum.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]]
+// HAS_ERRNO: declare double @llvm.maximumnum.f64(double, double) [[READNONE_INTRINSIC]]
+// HAS_ERRNO: declare float @llvm.maximumnum.f32(float, float) [[READNONE_INTRINSIC]]
+// HAS_ERRNO: declare x86_fp80 @llvm.maximumnum.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]]
+// HAS_MAYTRAP: declare double @llvm.experimental.constrained.maximumnum.f64(
+// HAS_MAYTRAP: declare float @llvm.experimental.constrained.maximumnum.f32(
+// HAS_MAYTRAP: declare x86_fp80 @llvm.experimental.constrained.maximumnum.f80(
+
+  fminimum_num(f,f);       fminimum_numf(f,f);      fminimum_numl(f,f);
+
+// NO__ERRNO: declare double @llvm.minimumnum.f64(double, double) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare float @llvm.minimumnum.f32(float, float) [[READNONE_INTRINSIC]]
+// NO__ERRNO: declare x86_fp80 @llvm.minimumnum.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]]
+// HAS_ERRNO: declare double @llvm.minimumnum.f64(double, double) [[READNONE_INTRINSIC]]
+// HAS_ERRNO: declare float @llvm.minimumnum.f32(float, float) [[READNONE_INTRINSIC]]
+// HAS_ERRNO: declare x86_fp80 @llvm.minimumnum.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]]
+// HAS_MAYTRAP: declare double @llvm.experimental.constrained.minimumnum.f64(
+// HAS_MAYTRAP: declare float @llvm.experimental.constrained.minimumnum.f32(
+// HAS_MAYTRAP: declare x86_fp80 @llvm.experimental.constrained.minimumnum.f80(
+
+
   hypot(f,f);      hypotf(f,f);     hypotl(f,f);
 
 // NO__ERRNO: declare double @hypot(double noundef, double noundef) [[READNONE]]
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 7b64c477d13c7..0a08b01d0a2b8 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -16049,6 +16049,84 @@ of the two arguments. -0.0 is considered to be less than +0.0 for this
 intrinsic. Note that these are the semantics specified in the draft of
 IEEE 754-2019.
 
+.. _i_minimumnum:
+
+'``llvm.minimumnum.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+This is an overloaded intrinsic. You can use ``llvm.minimumnum`` on any
+floating-point or vector of floating-point type. Not all targets support
+all types however.
+
+::
+
+      declare float     @llvm.minimumnum.f32(float %Val0, float %Val1)
+      declare double    @llvm.minimumnum.f64(double %Val0, double %Val1)
+      declare x86_fp80  @llvm.minimumnum.f80(x86_fp80 %Val0, x86_fp80 %Val1)
+      declare fp128     @llvm.minimumnum.f128(fp128 %Val0, fp128 %Val1)
+      declare ppc_fp128 @llvm.minimumnum.ppcf128(ppc_fp128 %Val0, ppc_fp128 %Val1)
+
+Overview:
+"""""""""
+
+The '``llvm.minimumnum.*``' intrinsics return the minimum of the two
+arguments, not propagating NaNs and treating -0.0 as less than +0.0.
+
+
+Arguments:
+""""""""""
+
+The arguments and return value are floating-point numbers of the same
+type.
+
+Semantics:
+""""""""""
+If both operands are NaNs, returns qNaN. Otherwise returns the lesser
+of the two arguments. -0.0 is considered to be less than +0.0 for this
+intrinsic. Note that these are the semantics specified in IEEE 754-2019.
+
+.. _i_maximumnum:
+
+'``llvm.maximumnum.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+This is an overloaded intrinsic. You can use ``llvm.maximumnum`` on any
+floating-point or vector of floating-point type. Not all targets support
+all types however.
+
+::
+
+      declare float     @llvm.maximumnum.f32(float %Val0, float %Val1)
+      declare double    @llvm.maximumnum.f64(double %Val0, double %Val1)
+      declare x86_fp80  @llvm.maximumnum.f80(x86_fp80 %Val0, x86_fp80 %Val1)
+      declare fp128     @llvm.maximumnum.f128(fp128 %Val0, fp128 %Val1)
+      declare ppc_fp128 @llvm.maximumnum.ppcf128(ppc_fp128 %Val0, ppc_fp128 %Val1)
+
+Overview:
+"""""""""
+
+The '``llvm.maximumnum.*``' intrinsics return the maximum of the two
+arguments, not propagating NaNs and treating -0.0 as less than +0.0.
+
+
+Arguments:
+""""""""""
+
+The arguments and return value are floating-point numbers of the same
+type.
+
+Semantics:
+""""""""""
+If both operands are NaNs, returns qNaN. Otherwise returns the greater
+of the two arguments. -0.0 is considered to be less than +0.0 for this
+intrinsic. Note that these are the semantics specified in IEEE 754-2019.
+
 .. _int_copysign:
 
 '``llvm.copysign.*``' Intrinsic
diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h
index 44a301ecc9928..fcfb05263a40f 100644
--- a/llvm/include/llvm/ADT/APFloat.h
+++ b/llvm/include/llvm/ADT/APFloat.h
@@ -1442,6 +1442,16 @@ inline APFloat minimum(const APFloat &A, const APFloat &B) {
     return A.isNegative() ? A : B;
   return B < A ? B : A;
 }
+LLVM_READONLY
+inline APFloat minimumnum(const APFloat &A, const APFloat &B) {
+  if (A.isNaN())
+    return B.isNaN() ? B.makeQuiet() : B;
+  if (B.isNaN())
+    return A;
+  if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative()))
+    return A.isNegative() ? A : B;
+  return B < A ? B : A;
+}
 
 /// Implements IEEE 754-2019 maximum semantics. Returns the larger of 2
 /// arguments, propagating NaNs and treating -0 as less than +0.
@@ -1455,6 +1465,16 @@ inline APFloat maximum(const APFloat &A, const APFloat &B) {
     return A.isNegative() ? B : A;
   return A < B ? B : A;
 }
+LLVM_READONLY
+inline APFloat maximumnum(const APFloat &A, const APFloat &B) {
+  if (A.isNaN())
+    return B.isNaN() ? B.makeQuiet() : B;
+  if (B.isNaN())
+    return A;
+  if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative()))
+    return A.isNegative() ? B : A;
+  return A < B ? B : A;
+}
 
 // We want the following functions to be available in the header for inlining.
 // We cannot define them inline in the class definition of `DoubleAPFloat`
diff --git a/llvm/include/llvm/Analysis/IVDescriptors.h b/llvm/include/llvm/Analysis/IVDescriptors.h
index 5c7b613ac48c4..107c9625f4f69 100644
--- a/llvm/include/llvm/Analysis/IVDescriptors.h
+++ b/llvm/include/llvm/Analysis/IVDescriptors.h
@@ -32,27 +32,29 @@ class StoreInst;
 
 /// These are the kinds of recurrences that we support.
 enum class RecurKind {
-  None,     ///< Not a recurrence.
-  Add,      ///< Sum of integers.
-  Mul,      ///< Product of integers.
-  Or,       ///< Bitwise or logical OR of integers.
-  And,      ///< Bitwise or logical AND of integers.
-  Xor,      ///< Bitwise or logical XOR of integers.
-  SMin,     ///< Signed integer min implemented in terms of select(cmp()).
-  SMax,     ///< Signed integer max implemented in terms of select(cmp()).
-  UMin,     ///< Unsigned integer min implemented in terms of select(cmp()).
-  UMax,     ///< Unsigned integer max implemented in terms of select(cmp()).
-  FAdd,     ///< Sum of floats.
-  FMul,     ///< Product of floats.
-  FMin,     ///< FP min implemented in terms of select(cmp()).
-  FMax,     ///< FP max implemented in terms of select(cmp()).
-  FMinimum, ///< FP min with llvm.minimum semantics
-  FMaximum, ///< FP max with llvm.maximum semantics
-  FMulAdd,  ///< Sum of float products with llvm.fmuladd(a * b + sum).
-  IAnyOf,   ///< Any_of reduction with select(icmp(),x,y) where one of (x,y) is
-            ///< loop invariant, and both x and y are integer type.
-  FAnyOf    ///< Any_of reduction with select(fcmp(),x,y) where one of (x,y) is
-            ///< loop invariant, and both x and y are integer type.
+  None,        ///< Not a recurrence.
+  Add,         ///< Sum of integers.
+  Mul,         ///< Product of integers.
+  Or,          ///< Bitwise or logical OR of integers.
+  And,         ///< Bitwise or logical AND of integers.
+  Xor,         ///< Bitwise or logical XOR of integers.
+  SMin,        ///< Signed integer min implemented in terms of select(cmp()).
+  SMax,        ///< Signed integer max implemented in terms of select(cmp()).
+  UMin,        ///< Unsigned integer min implemented in terms of select(cmp()).
+  UMax,        ///< Unsigned integer max implemented in terms of select(cmp()).
+  FAdd,        ///< Sum of floats.
+  FMul,        ///< Product of floats.
+  FMin,        ///< FP min implemented in terms of select(cmp()).
+  FMax,        ///< FP max implemented in terms of select(cmp()).
+  FMinimum,    ///< FP min with llvm.minimum semantics
+  FMaximum,    ///< FP max with llvm.maximum semantics
+  FMinimumnum, ///< FP min with llvm.minimumnum semantics
+  FMaximumnum, ///< FP max with llvm.maximumnum semantics
+  FMulAdd,     ///< Sum of float products with llvm.fmuladd(a * b + sum).
+  IAnyOf, ///< Any_of reduction with select(icmp(),x,y) where one of (x,y) is
+          ///< loop invariant, and both x and y are integer type.
+  FAnyOf  ///< Any_of reduction with select(fcmp(),x,y) where one of (x,y) is
+          ///< loop invariant, and both x and y are integer type.
   // TODO: Any_of reduction need not be restricted to integer type only.
 };
 
@@ -226,7 +228,8 @@ class RecurrenceDescriptor {
   /// Returns true if the recurrence kind is a floating-point min/max kind.
   static bool isFPMinMaxRecurrenceKind(RecurKind Kind) {
     return Kind == RecurKind::FMin || Kind == RecurKind::FMax ||
-           Kind == RecurKind::FMinimum || Kind == RecurKind::FMaximum;
+           Kind == RecurKind::FMinimum || Kind == RecurKind::FMaximum ||
+           Kind == RecurKind::FMinimumnum || Kind == RecurKind::FMaximumnum;
   }
 
   /// Returns true if the recurrence kind is any min/max kind.
diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
index 717693a7cf63c..8b938f97a679d 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.def
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
@@ -1347,6 +1347,39 @@ TLI_DEFINE_ENUM_INTERNAL(fminl)
 TLI_DEFINE_STRING_INTERNAL("fminl")
 TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
 
+// Calls to fmaximum_num and fminimum_num library functions expand to the llvm.maximumnum and
+// llvm.minimumnum intrinsics with the correct parameter types for the arguments
+// (all types must match).
+/// double fmaximum_num(double x, double y);
+TLI_DEFINE_ENUM_INTERNAL(fmaximum_num)
+TLI_DEFINE_STRING_INTERNAL("fmaximum_num")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// float fmaximum_numf(float x, float y);
+TLI_DEFINE_ENUM_INTERNAL(fmaximum_numf)
+TLI_DEFINE_STRING_INTERNAL("fmaximum_numf")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// long double fmaximum_numl(long double x, long double y);
+TLI_DEFINE_ENUM_INTERNAL(fmaximum_numl)
+TLI_DEFINE_STRING_INTERNAL("fmaximum_numl")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// double fminimum_num(double x, double y);
+TLI_DEFINE_ENUM_INTERNAL(fminimum_num)
+TLI_DEFINE_STRING_INTERNAL("fminimum_num")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// float fminimum_numf(float x, float y);
+TLI_DEFINE_ENUM_INTERNAL(fminimum_numf)
+TLI_DEFINE_STRING_INTERNAL("fminimum_numf")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// long double fminimum_numl(long double x, long double y);
+TLI_DEFINE_ENUM_INTERNAL(fminimum_numl)
+TLI_DEFINE_STRING_INTERNAL("fminimum_numl")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
 /// double fmod(double x, double y);
 TLI_DEFINE_ENUM_INTERNAL(fmod)
 TLI_DEFINE_STRING_INTERNAL("fmod")
diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 0584b7e29f67b..9a2250a67acdf 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -1059,14 +1059,16 @@ bool mustExecuteUBIfPoisonOnPathTo(Instruction *Root,
 /// Specific patterns of select instructions we can match.
 enum SelectPatternFlavor {
   SPF_UNKNOWN = 0,
-  SPF_SMIN,    /// Signed minimum
-  SPF_UMIN,    /// Unsigned minimum
-  SPF_SMAX,    /// Signed maximum
-  SPF_UMAX,    /// Unsigned maximum
-  SPF_FMINNUM, /// Floating point minnum
-  SPF_FMAXNUM, /// Floating point maxnum
-  SPF_ABS,     /// Absolute value
-  SPF_NABS     /// Negated absolute value
+  SPF_SMIN,        /// Signed minimum
+  SPF_UMIN,        /// Unsigned minimum
+  SPF_SMAX,        /// Signed maximum
+  SPF_UMAX,        /// Unsigned maximum
+  SPF_FMINNUM,     /// Floating point minnum
+  SPF_FMAXNUM,     /// Floating point maxnum
+  SPF_FMINIMUMNUM, /// Floating point minnum
+  SPF_FMAXIMUMNUM, /// Floating point maxnum
+  SPF_ABS,         /// Absolute value
+  SPF_NABS         /// Negated absolute value
 };
 
 /// Behavior when a floating point min/max is given one NaN and one
diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
index 2091432d4fe27..167cc2d1755a5 100644
--- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
@@ -1686,6 +1686,8 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
     case Intrinsic::vector_reduce_fmin:
     case Intrinsic::vector_reduce_fmaximum:
     case Intrinsic::vector_reduce_fminimum:
+    case Intrinsic::vector_reduce_fmaximumnum:
+    case Intrinsic::vector_reduce_fminimumnum:
     case Intrinsic::vector_reduce_umax:
     case Intrinsic::vector_reduce_umin: {
       IntrinsicCostAttributes Attrs(IID, RetTy, Args[0]->getType(), FMF, I, 1);
@@ -2009,6 +2011,12 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
     case Intrinsic::maximum:
       ISD = ISD::FMAXIMUM;
       break;
+    case Intrinsic::minimumnum:
+      ISD = ISD::FMINIMUMNUM;
+      break;
+   ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/93841


More information about the cfe-commits mailing list