llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-codegen 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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits