[llvm] Fill in some missing C23 math libcall handling (PR #170672)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 4 08:01:45 PST 2025
https://github.com/valadaptive updated https://github.com/llvm/llvm-project/pull/170672
>From 2cc5630e08a3b5f9708f1dc8703cd626c197c94a Mon Sep 17 00:00:00 2001
From: valadaptive <valadaptive at protonmail.com>
Date: Thu, 4 Dec 2025 10:37:27 -0500
Subject: [PATCH 01/13] [InstSimplify] Add roundeven constant-propagation tests
The libcall versions will later be optimized and constant-folded.
---
.../InstSimplify/ConstProp/roundeven.ll | 165 ++++++++++++++++++
1 file changed, 165 insertions(+)
create mode 100644 llvm/test/Transforms/InstSimplify/ConstProp/roundeven.ll
diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/roundeven.ll b/llvm/test/Transforms/InstSimplify/ConstProp/roundeven.ll
new file mode 100644
index 0000000000000..68938b3c6244c
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/ConstProp/roundeven.ll
@@ -0,0 +1,165 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=early-cse -earlycse-debug-hash < %s | FileCheck %s
+
+declare float @roundevenf(float) #0
+declare float @llvm.roundeven.f32(float)
+declare double @roundeven(double) #0
+declare double @llvm.roundeven.f64(double)
+
+define float @constant_fold_roundeven_f32_01() #0 {
+; CHECK-LABEL: define float @constant_fold_roundeven_f32_01(
+; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[X:%.*]] = call float @roundevenf(float 1.250000e+00) #[[ATTR0]]
+; CHECK-NEXT: ret float [[X]]
+;
+ %x = call float @roundevenf(float 1.25) #0
+ ret float %x
+}
+
+define float @constant_fold_roundeven_f32_02() #0 {
+; CHECK-LABEL: define float @constant_fold_roundeven_f32_02(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: ret float -1.000000e+00
+;
+ %x = call float @llvm.roundeven.f32(float -1.25) #0
+ ret float %x
+}
+
+; roundeven rounds ties to even, so 1.5 -> 2.0 (nearest even)
+define float @constant_fold_roundeven_f32_03() #0 {
+; CHECK-LABEL: define float @constant_fold_roundeven_f32_03(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: [[X:%.*]] = call float @roundevenf(float 1.500000e+00) #[[ATTR0]]
+; CHECK-NEXT: ret float [[X]]
+;
+ %x = call float @roundevenf(float 1.5) #0
+ ret float %x
+}
+
+; roundeven rounds ties to even, so -1.5 -> -2.0 (nearest even)
+define float @constant_fold_roundeven_f32_04() #0 {
+; CHECK-LABEL: define float @constant_fold_roundeven_f32_04(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: ret float -2.000000e+00
+;
+ %x = call float @llvm.roundeven.f32(float -1.5) #0
+ ret float %x
+}
+
+; roundeven rounds ties to even, so 2.5 -> 2.0 (nearest even)
+define float @constant_fold_roundeven_f32_05() #0 {
+; CHECK-LABEL: define float @constant_fold_roundeven_f32_05(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: [[X:%.*]] = call float @roundevenf(float 2.500000e+00) #[[ATTR0]]
+; CHECK-NEXT: ret float [[X]]
+;
+ %x = call float @roundevenf(float 2.5) #0
+ ret float %x
+}
+
+; roundeven rounds ties to even, so -2.5 -> -2.0 (nearest even)
+define float @constant_fold_roundeven_f32_06() #0 {
+; CHECK-LABEL: define float @constant_fold_roundeven_f32_06(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: ret float -2.000000e+00
+;
+ %x = call float @llvm.roundeven.f32(float -2.5) #0
+ ret float %x
+}
+
+define float @constant_fold_roundeven_f32_07() #0 {
+; CHECK-LABEL: define float @constant_fold_roundeven_f32_07(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: [[X:%.*]] = call float @roundevenf(float 2.750000e+00) #[[ATTR0]]
+; CHECK-NEXT: ret float [[X]]
+;
+ %x = call float @roundevenf(float 2.75) #0
+ ret float %x
+}
+
+define float @constant_fold_roundeven_f32_08() #0 {
+; CHECK-LABEL: define float @constant_fold_roundeven_f32_08(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: ret float -3.000000e+00
+;
+ %x = call float @llvm.roundeven.f32(float -2.75) #0
+ ret float %x
+}
+
+define double @constant_fold_roundeven_f64_01() #0 {
+; CHECK-LABEL: define double @constant_fold_roundeven_f64_01(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: [[X:%.*]] = call double @roundeven(double 1.300000e+00) #[[ATTR0]]
+; CHECK-NEXT: ret double [[X]]
+;
+ %x = call double @roundeven(double 1.3) #0
+ ret double %x
+}
+
+define double @constant_fold_roundeven_f64_02() #0 {
+; CHECK-LABEL: define double @constant_fold_roundeven_f64_02(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: ret double -1.000000e+00
+;
+ %x = call double @llvm.roundeven.f64(double -1.3) #0
+ ret double %x
+}
+
+define double @constant_fold_roundeven_f64_03() #0 {
+; CHECK-LABEL: define double @constant_fold_roundeven_f64_03(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: [[X:%.*]] = call double @roundeven(double 1.500000e+00) #[[ATTR0]]
+; CHECK-NEXT: ret double [[X]]
+;
+ %x = call double @roundeven(double 1.5) #0
+ ret double %x
+}
+
+define double @constant_fold_roundeven_f64_04() #0 {
+; CHECK-LABEL: define double @constant_fold_roundeven_f64_04(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: ret double -2.000000e+00
+;
+ %x = call double @llvm.roundeven.f64(double -1.5) #0
+ ret double %x
+}
+
+define double @constant_fold_roundeven_f64_05() #0 {
+; CHECK-LABEL: define double @constant_fold_roundeven_f64_05(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: [[X:%.*]] = call double @roundeven(double 2.500000e+00) #[[ATTR0]]
+; CHECK-NEXT: ret double [[X]]
+;
+ %x = call double @roundeven(double 2.5) #0
+ ret double %x
+}
+
+define double @constant_fold_roundeven_f64_06() #0 {
+; CHECK-LABEL: define double @constant_fold_roundeven_f64_06(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: ret double -2.000000e+00
+;
+ %x = call double @llvm.roundeven.f64(double -2.5) #0
+ ret double %x
+}
+
+define double @constant_fold_roundeven_f64_07() #0 {
+; CHECK-LABEL: define double @constant_fold_roundeven_f64_07(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: [[X:%.*]] = call double @roundeven(double 2.700000e+00) #[[ATTR0]]
+; CHECK-NEXT: ret double [[X]]
+;
+ %x = call double @roundeven(double 2.7) #0
+ ret double %x
+}
+
+define double @constant_fold_roundeven_f64_08() #0 {
+; CHECK-LABEL: define double @constant_fold_roundeven_f64_08(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: ret double -3.000000e+00
+;
+ %x = call double @llvm.roundeven.f64(double -2.7) #0
+ ret double %x
+}
+
+attributes #0 = { nounwind readnone willreturn }
>From 416811a24f06c8cae99116d9cd9509b58e079afe Mon Sep 17 00:00:00 2001
From: valadaptive <valadaptive at protonmail.com>
Date: Thu, 4 Dec 2025 07:48:07 -0500
Subject: [PATCH 02/13] [InferAttrs] Mark ceil and round as memory(none)
This probably should've been done in
https://github.com/llvm/llvm-project/pull/124742, but it wasn't. The
floor, ceil, round, and trunc family of functions all behave the same.
---
llvm/lib/Transforms/Utils/BuildLibCalls.cpp | 12 ++++++------
llvm/test/Transforms/InferFunctionAttrs/annotate.ll | 12 ++++++------
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
index 02b73e85d783f..213869fb993d7 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -1227,9 +1227,6 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_atanhf:
case LibFunc_atanhl:
case LibFunc_atanl:
- case LibFunc_ceil:
- case LibFunc_ceilf:
- case LibFunc_ceill:
case LibFunc_cos:
case LibFunc_cosh:
case LibFunc_coshf:
@@ -1298,9 +1295,6 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_rint:
case LibFunc_rintf:
case LibFunc_rintl:
- case LibFunc_round:
- case LibFunc_roundf:
- case LibFunc_roundl:
case LibFunc_scalbln:
case LibFunc_scalblnf:
case LibFunc_scalblnl:
@@ -1338,6 +1332,9 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_copysign:
case LibFunc_copysignf:
case LibFunc_copysignl:
+ case LibFunc_ceil:
+ case LibFunc_ceilf:
+ case LibFunc_ceill:
case LibFunc_fabs:
case LibFunc_fabsf:
case LibFunc_fabsl:
@@ -1361,6 +1358,9 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_nearbyint:
case LibFunc_nearbyintf:
case LibFunc_nearbyintl:
+ case LibFunc_round:
+ case LibFunc_roundf:
+ case LibFunc_roundl:
case LibFunc_toascii:
case LibFunc_trunc:
case LibFunc_truncf:
diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
index 25a70a026a0b7..4a0a20b71dfde 100644
--- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
+++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
@@ -304,13 +304,13 @@ declare float @cbrtf(float)
; CHECK: declare x86_fp80 @cbrtl(x86_fp80) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
declare x86_fp80 @cbrtl(x86_fp80)
-; CHECK: declare double @ceil(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+; CHECK: declare double @ceil(double) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
declare double @ceil(double)
-; CHECK: declare float @ceilf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+; CHECK: declare float @ceilf(float) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
declare float @ceilf(float)
-; CHECK: declare x86_fp80 @ceill(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+; CHECK: declare x86_fp80 @ceill(x86_fp80) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
declare x86_fp80 @ceill(x86_fp80)
; The second argument of int chmod(FILE*, mode_t) is a 32-bit int on most
@@ -909,13 +909,13 @@ declare x86_fp80 @rintl(x86_fp80)
; CHECK: declare noundef i32 @rmdir(ptr noundef readonly captures(none)) [[NOFREE_NOUNWIND]]
declare i32 @rmdir(ptr)
-; CHECK: declare double @round(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+; CHECK: declare double @round(double) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
declare double @round(double)
-; CHECK: declare float @roundf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+; CHECK: declare float @roundf(float) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
declare float @roundf(float)
-; CHECK: declare x86_fp80 @roundl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+; CHECK: declare x86_fp80 @roundl(x86_fp80) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
declare x86_fp80 @roundl(x86_fp80)
; CHECK: declare double @scalbln(double, i64) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
>From a50096bf4fbd31dd847aabbf1df3e5f1042c3f92 Mon Sep 17 00:00:00 2001
From: valadaptive <valadaptive at protonmail.com>
Date: Thu, 4 Dec 2025 10:39:28 -0500
Subject: [PATCH 03/13] [TLI] Handle roundeven libcall in hasOptimizedCodegen
This is a prerequisite to being able to turn it into an intrinsic.
---
llvm/include/llvm/Analysis/TargetLibraryInfo.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.h b/llvm/include/llvm/Analysis/TargetLibraryInfo.h
index 0f98af69f12c6..a88497beb20ae 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.h
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.h
@@ -417,6 +417,7 @@ class TargetLibraryInfo {
case LibFunc_nearbyint: case LibFunc_nearbyintf: case LibFunc_nearbyintl:
case LibFunc_rint: case LibFunc_rintf: case LibFunc_rintl:
case LibFunc_round: case LibFunc_roundf: case LibFunc_roundl:
+ case LibFunc_roundeven: case LibFunc_roundevenf: case LibFunc_roundevenl:
case LibFunc_sin: case LibFunc_sinf: case LibFunc_sinl:
case LibFunc_sinh: case LibFunc_sinhf: case LibFunc_sinhl:
case LibFunc_sqrt: case LibFunc_sqrtf: case LibFunc_sqrtl:
>From 28589a3a2f223c05b1138b6f86107aa9b203998d Mon Sep 17 00:00:00 2001
From: valadaptive <valadaptive at protonmail.com>
Date: Thu, 4 Dec 2025 10:40:01 -0500
Subject: [PATCH 04/13] [SelectionDAG] Handle roundeven libcall in visitCall
We can now lower it to its proper instruction.
---
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 09a0673bfe1bb..6f22730c90efe 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -9710,6 +9710,12 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) {
if (visitUnaryFloatCall(I, ISD::FROUND))
return;
break;
+ case LibFunc_roundeven:
+ case LibFunc_roundevenf:
+ case LibFunc_roundevenl:
+ if (visitUnaryFloatCall(I, ISD::FROUNDEVEN))
+ return;
+ break;
case LibFunc_trunc:
case LibFunc_truncf:
case LibFunc_truncl:
>From 2536928fab13c63602620f93be673c545934b1fa Mon Sep 17 00:00:00 2001
From: valadaptive <valadaptive at protonmail.com>
Date: Thu, 4 Dec 2025 10:40:55 -0500
Subject: [PATCH 05/13] [InferAttrs] Handle roundeven like other libm functions
It was previously missing entirely. It behaves like floor, ceil, round,
and trunc, having no side effects.
---
llvm/lib/Transforms/Utils/BuildLibCalls.cpp | 3 +++
llvm/test/Transforms/InferFunctionAttrs/annotate.ll | 9 +++++++++
2 files changed, 12 insertions(+)
diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
index 213869fb993d7..05c882da38d61 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -1361,6 +1361,9 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_round:
case LibFunc_roundf:
case LibFunc_roundl:
+ case LibFunc_roundeven:
+ case LibFunc_roundevenf:
+ case LibFunc_roundevenl:
case LibFunc_toascii:
case LibFunc_trunc:
case LibFunc_truncf:
diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
index 4a0a20b71dfde..f5020a93250ea 100644
--- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
+++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
@@ -918,6 +918,15 @@ declare float @roundf(float)
; CHECK: declare x86_fp80 @roundl(x86_fp80) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
declare x86_fp80 @roundl(x86_fp80)
+; CHECK: declare double @roundeven(double) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+declare double @roundeven(double)
+
+; CHECK: declare float @roundevenf(float) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+declare float @roundevenf(float)
+
+; CHECK: declare x86_fp80 @roundevenl(x86_fp80) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+declare x86_fp80 @roundevenl(x86_fp80)
+
; CHECK: declare double @scalbln(double, i64) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
declare double @scalbln(double, i64)
>From d0d46899144e3b4b9384b257ce93fa7c5b838b1d Mon Sep 17 00:00:00 2001
From: valadaptive <valadaptive at protonmail.com>
Date: Thu, 4 Dec 2025 10:42:03 -0500
Subject: [PATCH 06/13] [ConstantFolding] Handle roundeven libcalls
Basically identical to nearbyint and rint, which we already treat as
rounding to nearest with ties to even during constant folding.
---
llvm/lib/Analysis/ConstantFolding.cpp | 10 ++++++--
.../InstSimplify/ConstProp/roundeven.ll | 24 +++++++------------
2 files changed, 16 insertions(+), 18 deletions(-)
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 63d12ee585e64..b39b32042dd2f 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -1984,6 +1984,7 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
switch (Name[0]) {
default:
return false;
+ // clang-format off
case 'a':
return Name == "acos" || Name == "acosf" ||
Name == "asin" || Name == "asinf" ||
@@ -2014,7 +2015,8 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
case 'r':
return Name == "remainder" || Name == "remainderf" ||
Name == "rint" || Name == "rintf" ||
- Name == "round" || Name == "roundf";
+ Name == "round" || Name == "roundf" ||
+ Name == "roundeven" || Name == "roundevenf";
case 's':
return Name == "sin" || Name == "sinf" ||
Name == "sinh" || Name == "sinhf" ||
@@ -2052,6 +2054,7 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
case 's':
return Name == "__sinh_finite" || Name == "__sinhf_finite";
}
+ // clang-format on
}
}
@@ -2516,7 +2519,8 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
// Use internal versions of these intrinsics.
- if (IntrinsicID == Intrinsic::nearbyint || IntrinsicID == Intrinsic::rint) {
+ if (IntrinsicID == Intrinsic::nearbyint || IntrinsicID == Intrinsic::rint ||
+ IntrinsicID == Intrinsic::roundeven) {
U.roundToIntegral(APFloat::rmNearestTiesToEven);
return ConstantFP::get(Ty->getContext(), U);
}
@@ -2988,6 +2992,8 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
case LibFunc_nearbyintf:
case LibFunc_rint:
case LibFunc_rintf:
+ case LibFunc_roundeven:
+ case LibFunc_roundevenf:
if (TLI->has(Func)) {
U.roundToIntegral(APFloat::rmNearestTiesToEven);
return ConstantFP::get(Ty->getContext(), U);
diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/roundeven.ll b/llvm/test/Transforms/InstSimplify/ConstProp/roundeven.ll
index 68938b3c6244c..e6448847112fb 100644
--- a/llvm/test/Transforms/InstSimplify/ConstProp/roundeven.ll
+++ b/llvm/test/Transforms/InstSimplify/ConstProp/roundeven.ll
@@ -9,8 +9,7 @@ declare double @llvm.roundeven.f64(double)
define float @constant_fold_roundeven_f32_01() #0 {
; CHECK-LABEL: define float @constant_fold_roundeven_f32_01(
; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
-; CHECK-NEXT: [[X:%.*]] = call float @roundevenf(float 1.250000e+00) #[[ATTR0]]
-; CHECK-NEXT: ret float [[X]]
+; CHECK-NEXT: ret float 1.000000e+00
;
%x = call float @roundevenf(float 1.25) #0
ret float %x
@@ -29,8 +28,7 @@ define float @constant_fold_roundeven_f32_02() #0 {
define float @constant_fold_roundeven_f32_03() #0 {
; CHECK-LABEL: define float @constant_fold_roundeven_f32_03(
; CHECK-SAME: ) #[[ATTR0]] {
-; CHECK-NEXT: [[X:%.*]] = call float @roundevenf(float 1.500000e+00) #[[ATTR0]]
-; CHECK-NEXT: ret float [[X]]
+; CHECK-NEXT: ret float 2.000000e+00
;
%x = call float @roundevenf(float 1.5) #0
ret float %x
@@ -50,8 +48,7 @@ define float @constant_fold_roundeven_f32_04() #0 {
define float @constant_fold_roundeven_f32_05() #0 {
; CHECK-LABEL: define float @constant_fold_roundeven_f32_05(
; CHECK-SAME: ) #[[ATTR0]] {
-; CHECK-NEXT: [[X:%.*]] = call float @roundevenf(float 2.500000e+00) #[[ATTR0]]
-; CHECK-NEXT: ret float [[X]]
+; CHECK-NEXT: ret float 2.000000e+00
;
%x = call float @roundevenf(float 2.5) #0
ret float %x
@@ -70,8 +67,7 @@ define float @constant_fold_roundeven_f32_06() #0 {
define float @constant_fold_roundeven_f32_07() #0 {
; CHECK-LABEL: define float @constant_fold_roundeven_f32_07(
; CHECK-SAME: ) #[[ATTR0]] {
-; CHECK-NEXT: [[X:%.*]] = call float @roundevenf(float 2.750000e+00) #[[ATTR0]]
-; CHECK-NEXT: ret float [[X]]
+; CHECK-NEXT: ret float 3.000000e+00
;
%x = call float @roundevenf(float 2.75) #0
ret float %x
@@ -89,8 +85,7 @@ define float @constant_fold_roundeven_f32_08() #0 {
define double @constant_fold_roundeven_f64_01() #0 {
; CHECK-LABEL: define double @constant_fold_roundeven_f64_01(
; CHECK-SAME: ) #[[ATTR0]] {
-; CHECK-NEXT: [[X:%.*]] = call double @roundeven(double 1.300000e+00) #[[ATTR0]]
-; CHECK-NEXT: ret double [[X]]
+; CHECK-NEXT: ret double 1.000000e+00
;
%x = call double @roundeven(double 1.3) #0
ret double %x
@@ -108,8 +103,7 @@ define double @constant_fold_roundeven_f64_02() #0 {
define double @constant_fold_roundeven_f64_03() #0 {
; CHECK-LABEL: define double @constant_fold_roundeven_f64_03(
; CHECK-SAME: ) #[[ATTR0]] {
-; CHECK-NEXT: [[X:%.*]] = call double @roundeven(double 1.500000e+00) #[[ATTR0]]
-; CHECK-NEXT: ret double [[X]]
+; CHECK-NEXT: ret double 2.000000e+00
;
%x = call double @roundeven(double 1.5) #0
ret double %x
@@ -127,8 +121,7 @@ define double @constant_fold_roundeven_f64_04() #0 {
define double @constant_fold_roundeven_f64_05() #0 {
; CHECK-LABEL: define double @constant_fold_roundeven_f64_05(
; CHECK-SAME: ) #[[ATTR0]] {
-; CHECK-NEXT: [[X:%.*]] = call double @roundeven(double 2.500000e+00) #[[ATTR0]]
-; CHECK-NEXT: ret double [[X]]
+; CHECK-NEXT: ret double 2.000000e+00
;
%x = call double @roundeven(double 2.5) #0
ret double %x
@@ -146,8 +139,7 @@ define double @constant_fold_roundeven_f64_06() #0 {
define double @constant_fold_roundeven_f64_07() #0 {
; CHECK-LABEL: define double @constant_fold_roundeven_f64_07(
; CHECK-SAME: ) #[[ATTR0]] {
-; CHECK-NEXT: [[X:%.*]] = call double @roundeven(double 2.700000e+00) #[[ATTR0]]
-; CHECK-NEXT: ret double [[X]]
+; CHECK-NEXT: ret double 3.000000e+00
;
%x = call double @roundeven(double 2.7) #0
ret double %x
>From 09cae4b5053c58ac1dba8072016841df51e10962 Mon Sep 17 00:00:00 2001
From: valadaptive <valadaptive at protonmail.com>
Date: Thu, 4 Dec 2025 10:42:19 -0500
Subject: [PATCH 07/13] [NumericalStabilitySanitizer] Handle roundeven libcalls
Here, it's a simple matter of wiring them up.
---
.../Transforms/Instrumentation/NumericalStabilitySanitizer.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp
index 66d570b3f831e..3bbf049a1d8b9 100644
--- a/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp
@@ -1514,6 +1514,9 @@ const KnownIntrinsic::LFEntry KnownIntrinsic::kLibfuncIntrinsics[] = {
{LibFunc_roundf, "llvm.round.f32"},
{LibFunc_round, "llvm.round.f64"},
{LibFunc_roundl, "llvm.round.f80"},
+ {LibFunc_roundevenf, "llvm.roundeven.f32"},
+ {LibFunc_roundeven, "llvm.roundeven.f64"},
+ {LibFunc_roundevenl, "llvm.roundeven.f80"},
};
const char *KnownIntrinsic::get(LibFunc LFunc) {
>From 3fb29b79894cee481142d49cf59d9ed368629fd1 Mon Sep 17 00:00:00 2001
From: valadaptive <valadaptive at protonmail.com>
Date: Thu, 4 Dec 2025 10:37:16 -0500
Subject: [PATCH 08/13] [InstCombine] Add regression tests for
f[min][max]imum_num libcalls
Add tests corresponding to the existing fmin/fmax tests, as we'll later
begin optimizing these into intrinsics.
---
.../InstCombine/float-shrink-compare.ll | 36 +++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/float-shrink-compare.ll b/llvm/test/Transforms/InstCombine/float-shrink-compare.ll
index 77b6ed7c5abe8..46341cf3d346f 100644
--- a/llvm/test/Transforms/InstCombine/float-shrink-compare.ll
+++ b/llvm/test/Transforms/InstCombine/float-shrink-compare.ll
@@ -463,6 +463,40 @@ define i1 @test18(float %x, float %y, float %z) {
ret i1 %5
}
+define i1 @test_fminimum_num(float %x, float %y, float %z) {
+; CHECK-LABEL: @test_fminimum_num(
+; CHECK-NEXT: [[TMP1:%.*]] = fpext float [[X:%.*]] to double
+; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[Y:%.*]] to double
+; CHECK-NEXT: [[TMP3:%.*]] = call double @fminimum_num(double [[TMP1]], double [[TMP2]]) #[[ATTR3:[0-9]+]]
+; CHECK-NEXT: [[TMP4:%.*]] = fpext float [[Z:%.*]] to double
+; CHECK-NEXT: [[TMP5:%.*]] = fcmp oeq double [[TMP3]], [[TMP4]]
+; CHECK-NEXT: ret i1 [[TMP5]]
+;
+ %1 = fpext float %x to double
+ %2 = fpext float %y to double
+ %3 = call double @fminimum_num(double %1, double %2) nounwind
+ %4 = fpext float %z to double
+ %5 = fcmp oeq double %3, %4
+ ret i1 %5
+}
+
+define i1 @test_fmaximum_num(float %x, float %y, float %z) {
+; CHECK-LABEL: @test_fmaximum_num(
+; CHECK-NEXT: [[TMP1:%.*]] = fpext float [[X:%.*]] to double
+; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[Y:%.*]] to double
+; CHECK-NEXT: [[TMP3:%.*]] = call double @fmaximum_num(double [[TMP1]], double [[TMP2]]) #[[ATTR3]]
+; CHECK-NEXT: [[TMP4:%.*]] = fpext float [[Z:%.*]] to double
+; CHECK-NEXT: [[TMP5:%.*]] = fcmp oeq double [[TMP3]], [[TMP4]]
+; CHECK-NEXT: ret i1 [[TMP5]]
+;
+ %1 = fpext float %x to double
+ %2 = fpext float %y to double
+ %3 = call double @fmaximum_num(double %1, double %2) nounwind
+ %4 = fpext float %z to double
+ %5 = fcmp oeq double %3, %4
+ ret i1 %5
+}
+
define i1 @test19(float %x, float %y, float %z) {
; CHECK-LABEL: @test19(
; CHECK-NEXT: [[COPYSIGNF:%.*]] = call float @copysignf(float [[X:%.*]], float [[Y:%.*]]) #[[ATTR0:[0-9]+]]
@@ -518,6 +552,8 @@ declare double @roundeven(double) nounwind readnone
declare double @trunc(double) nounwind readnone
declare double @fmin(double, double) nounwind readnone
declare double @fmax(double, double) nounwind readnone
+declare double @fminimum_num(double, double) nounwind readnone
+declare double @fmaximum_num(double, double) nounwind readnone
declare double @llvm.fabs.f64(double) nounwind readnone
declare double @llvm.ceil.f64(double) nounwind readnone
>From 95677da47cf749cff3c4f32740da2a1e228e87b3 Mon Sep 17 00:00:00 2001
From: valadaptive <valadaptive at protonmail.com>
Date: Thu, 4 Dec 2025 10:42:54 -0500
Subject: [PATCH 09/13] [TLI] Handle f[min/max]imum_num in hasOptimizedCodegen
This is a prerequisite to lowering them to intrinsics later.
---
llvm/include/llvm/Analysis/TargetLibraryInfo.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.h b/llvm/include/llvm/Analysis/TargetLibraryInfo.h
index a88497beb20ae..022f0dbb04421 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.h
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.h
@@ -410,6 +410,10 @@ class TargetLibraryInfo {
case LibFunc_floor: case LibFunc_floorf: case LibFunc_floorl:
case LibFunc_fmax: case LibFunc_fmaxf: case LibFunc_fmaxl:
case LibFunc_fmin: case LibFunc_fminf: case LibFunc_fminl:
+ case LibFunc_fmaximum_num: case LibFunc_fmaximum_numf:
+ case LibFunc_fmaximum_numl:
+ case LibFunc_fminimum_num: case LibFunc_fminimum_numf:
+ case LibFunc_fminimum_numl:
case LibFunc_ldexp: case LibFunc_ldexpf: case LibFunc_ldexpl:
case LibFunc_log2: case LibFunc_log2f: case LibFunc_log2l:
case LibFunc_memcmp: case LibFunc_bcmp: case LibFunc_strcmp:
>From e0a160bed23ba133a70aea408c621fe6dbe1e051 Mon Sep 17 00:00:00 2001
From: valadaptive <valadaptive at protonmail.com>
Date: Thu, 4 Dec 2025 10:43:22 -0500
Subject: [PATCH 10/13] [InferAttrs] Handle f[min/max]imum_num like other libm
functions
These behave like fmin and fmax.
---
llvm/lib/Transforms/Utils/BuildLibCalls.cpp | 6 ++++++
.../Transforms/InferFunctionAttrs/annotate.ll | 18 ++++++++++++++++++
2 files changed, 24 insertions(+)
diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
index 05c882da38d61..a245b9405cfb7 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -1353,6 +1353,12 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
case LibFunc_fmin:
case LibFunc_fminf:
case LibFunc_fminl:
+ case LibFunc_fmaximum_num:
+ case LibFunc_fmaximum_numf:
+ case LibFunc_fmaximum_numl:
+ case LibFunc_fminimum_num:
+ case LibFunc_fminimum_numf:
+ case LibFunc_fminimum_numl:
case LibFunc_labs:
case LibFunc_llabs:
case LibFunc_nearbyint:
diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
index f5020a93250ea..27ae0d53350f4 100644
--- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
+++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll
@@ -473,6 +473,24 @@ declare float @fminf(float, float)
; CHECK: declare x86_fp80 @fminl(x86_fp80, x86_fp80) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
declare x86_fp80 @fminl(x86_fp80, x86_fp80)
+; CHECK: declare double @fmaximum_num(double, double) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+declare double @fmaximum_num(double, double)
+
+; CHECK: declare float @fmaximum_numf(float, float) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+declare float @fmaximum_numf(float, float)
+
+; CHECK: declare x86_fp80 @fmaximum_numl(x86_fp80, x86_fp80) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+declare x86_fp80 @fmaximum_numl(x86_fp80, x86_fp80)
+
+; CHECK: declare double @fminimum_num(double, double) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+declare double @fminimum_num(double, double)
+
+; CHECK: declare float @fminimum_numf(float, float) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+declare float @fminimum_numf(float, float)
+
+; CHECK: declare x86_fp80 @fminimum_numl(x86_fp80, x86_fp80) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
+declare x86_fp80 @fminimum_numl(x86_fp80, x86_fp80)
+
; CHECK: declare double @fmod(double, double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]]
declare double @fmod(double, double)
>From 3696d6254fedd41f6184adb012ef63b2a0a7b77b Mon Sep 17 00:00:00 2001
From: valadaptive <valadaptive at protonmail.com>
Date: Thu, 4 Dec 2025 10:44:16 -0500
Subject: [PATCH 11/13] [ValueTracking] Handle f[min/max]imum_num in
getIntrinsicForCallSite
A straightforward mapping onto the corresponding intrinsic.
---
llvm/lib/Analysis/ValueTracking.cpp | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 9cb6f19b9340c..6de4f57f75273 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4680,6 +4680,14 @@ Intrinsic::ID llvm::getIntrinsicForCallSite(const CallBase &CB,
case LibFunc_fmaxf:
case LibFunc_fmaxl:
return Intrinsic::maxnum;
+ case LibFunc_fminimum_num:
+ case LibFunc_fminimum_numf:
+ case LibFunc_fminimum_numl:
+ return Intrinsic::minimumnum;
+ case LibFunc_fmaximum_num:
+ case LibFunc_fmaximum_numf:
+ case LibFunc_fmaximum_numl:
+ return Intrinsic::maximumnum;
case LibFunc_copysign:
case LibFunc_copysignf:
case LibFunc_copysignl:
>From 11e899cfa8970d8e93db9a011904b59e986faf32 Mon Sep 17 00:00:00 2001
From: valadaptive <valadaptive at protonmail.com>
Date: Thu, 4 Dec 2025 10:44:47 -0500
Subject: [PATCH 12/13] [SimplifyLibCalls] Recognize and simplify
f[min/max]imumnum
Unlike fmin and fmax, these are deterministic with regards to signed
zero.
---
.../llvm/Transforms/Utils/SimplifyLibCalls.h | 1 +
.../lib/Transforms/Utils/SimplifyLibCalls.cpp | 31 +++++++++++++++++++
.../InstCombine/float-shrink-compare.ll | 14 +++------
3 files changed, 36 insertions(+), 10 deletions(-)
diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
index 4e7c97194cc59..64d2512308935 100644
--- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
+++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -205,6 +205,7 @@ class LibCallSimplifier {
Value *replacePowWithSqrt(CallInst *Pow, IRBuilderBase &B);
Value *optimizeExp2(CallInst *CI, IRBuilderBase &B);
Value *optimizeFMinFMax(CallInst *CI, IRBuilderBase &B);
+ Value *optimizeFMinimumnumFMaximumnum(CallInst *CI, IRBuilderBase &B);
Value *optimizeLog(CallInst *CI, IRBuilderBase &B);
Value *optimizeSqrt(CallInst *CI, IRBuilderBase &B);
Value *optimizeFMod(CallInst *CI, IRBuilderBase &B);
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index d1548694baa27..20d9b03bd87c8 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -2543,6 +2543,30 @@ Value *LibCallSimplifier::optimizeFMinFMax(CallInst *CI, IRBuilderBase &B) {
CI->getArgOperand(1), FMF));
}
+Value *LibCallSimplifier::optimizeFMinimumnumFMaximumnum(CallInst *CI,
+ IRBuilderBase &B) {
+ Module *M = CI->getModule();
+
+ // If we can shrink the call to a float function rather than a double
+ // function, do that first.
+ Function *Callee = CI->getCalledFunction();
+ StringRef Name = Callee->getName();
+ if ((Name == "fminimum_num" || Name == "fmaximum_num") &&
+ hasFloatVersion(M, Name))
+ if (Value *Ret = optimizeBinaryDoubleFP(CI, B, TLI))
+ return Ret;
+
+ // The new fminimum_num/fmaximum_num functions, unlike fmin/fmax, *are*
+ // sensitive to the sigh of zero, so we don't change the fast-math flags like
+ // we did for those.
+
+ Intrinsic::ID IID = Callee->getName().starts_with("fminimum_num")
+ ? Intrinsic::minimumnum
+ : Intrinsic::maximumnum;
+ return copyFlags(*CI, B.CreateBinaryIntrinsic(IID, CI->getArgOperand(0),
+ CI->getArgOperand(1), CI));
+}
+
Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) {
Function *LogFn = Log->getCalledFunction();
StringRef LogNm = LogFn->getName();
@@ -4123,6 +4147,13 @@ Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
case LibFunc_fmax:
case LibFunc_fmaxl:
return optimizeFMinFMax(CI, Builder);
+ case LibFunc_fminimum_numf:
+ case LibFunc_fminimum_num:
+ case LibFunc_fminimum_numl:
+ case LibFunc_fmaximum_numf:
+ case LibFunc_fmaximum_num:
+ case LibFunc_fmaximum_numl:
+ return optimizeFMinimumnumFMaximumnum(CI, Builder);
case LibFunc_cabs:
case LibFunc_cabsf:
case LibFunc_cabsl:
diff --git a/llvm/test/Transforms/InstCombine/float-shrink-compare.ll b/llvm/test/Transforms/InstCombine/float-shrink-compare.ll
index 46341cf3d346f..6383feff3a6ee 100644
--- a/llvm/test/Transforms/InstCombine/float-shrink-compare.ll
+++ b/llvm/test/Transforms/InstCombine/float-shrink-compare.ll
@@ -465,11 +465,8 @@ define i1 @test18(float %x, float %y, float %z) {
define i1 @test_fminimum_num(float %x, float %y, float %z) {
; CHECK-LABEL: @test_fminimum_num(
-; CHECK-NEXT: [[TMP1:%.*]] = fpext float [[X:%.*]] to double
-; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[Y:%.*]] to double
-; CHECK-NEXT: [[TMP3:%.*]] = call double @fminimum_num(double [[TMP1]], double [[TMP2]]) #[[ATTR3:[0-9]+]]
-; CHECK-NEXT: [[TMP4:%.*]] = fpext float [[Z:%.*]] to double
-; CHECK-NEXT: [[TMP5:%.*]] = fcmp oeq double [[TMP3]], [[TMP4]]
+; CHECK-NEXT: [[FMINIMUM_NUMF:%.*]] = call float @llvm.minimumnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT: [[TMP5:%.*]] = fcmp oeq float [[FMINIMUM_NUMF]], [[Z:%.*]]
; CHECK-NEXT: ret i1 [[TMP5]]
;
%1 = fpext float %x to double
@@ -482,11 +479,8 @@ define i1 @test_fminimum_num(float %x, float %y, float %z) {
define i1 @test_fmaximum_num(float %x, float %y, float %z) {
; CHECK-LABEL: @test_fmaximum_num(
-; CHECK-NEXT: [[TMP1:%.*]] = fpext float [[X:%.*]] to double
-; CHECK-NEXT: [[TMP2:%.*]] = fpext float [[Y:%.*]] to double
-; CHECK-NEXT: [[TMP3:%.*]] = call double @fmaximum_num(double [[TMP1]], double [[TMP2]]) #[[ATTR3]]
-; CHECK-NEXT: [[TMP4:%.*]] = fpext float [[Z:%.*]] to double
-; CHECK-NEXT: [[TMP5:%.*]] = fcmp oeq double [[TMP3]], [[TMP4]]
+; CHECK-NEXT: [[FMAXIMUM_NUMF:%.*]] = call float @llvm.maximumnum.f32(float [[X:%.*]], float [[Y:%.*]])
+; CHECK-NEXT: [[TMP5:%.*]] = fcmp oeq float [[FMAXIMUM_NUMF]], [[Z:%.*]]
; CHECK-NEXT: ret i1 [[TMP5]]
;
%1 = fpext float %x to double
>From f055c83345390fcdb6aadc7d2fd3d0d95e1435e4 Mon Sep 17 00:00:00 2001
From: valadaptive <valadaptive at protonmail.com>
Date: Thu, 4 Dec 2025 10:45:13 -0500
Subject: [PATCH 13/13] [NumericalStabilitySanitizer] Handle f[min/max]imum_num
libcalls
A simple matter of adding them to the table.
---
.../Instrumentation/NumericalStabilitySanitizer.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp
index 3bbf049a1d8b9..8b1d765d77818 100644
--- a/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp
@@ -1499,6 +1499,12 @@ const KnownIntrinsic::LFEntry KnownIntrinsic::kLibfuncIntrinsics[] = {
{LibFunc_fminf, "llvm.minnum.f32"},
{LibFunc_fmin, "llvm.minnum.f64"},
{LibFunc_fminl, "llvm.minnum.f80"},
+ {LibFunc_fmaximum_numf, "llvm.maximumnum.f32"},
+ {LibFunc_fmaximum_num, "llvm.maximumnum.f64"},
+ {LibFunc_fmaximum_numl, "llvm.maximumnum.f80"},
+ {LibFunc_fminimum_numf, "llvm.minimumnum.f32"},
+ {LibFunc_fminimum_num, "llvm.minimumnum.f64"},
+ {LibFunc_fminimum_numl, "llvm.minimumnum.f80"},
{LibFunc_ceilf, "llvm.ceil.f32"},
{LibFunc_ceil, "llvm.ceil.f64"},
{LibFunc_ceill, "llvm.ceil.f80"},
More information about the llvm-commits
mailing list