[llvm] [ConstantFolding] Add constant folding support for nextafter/nexttoward (PR #167324)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 10 11:04:33 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Sayan Sivakumaran (sivakusayan)
<details>
<summary>Changes</summary>
Fixes issue #<!-- -->74368.
This patch enables us to constant fold `nextafter` and `nexttoward` as long as we know that `errno` won't be written. In the latter case, we should keep the function call so the programmer can observe the side effect.
Apologies for the large patch, the majority of it are `lit` tests. I wasn't sure how to cut down on the repetitiveness here, let me know if you have any better ideas. I got the idea for reusing the constants across `.ll` files from the LLVM Discord.
---
Patch is 38.99 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/167324.diff
7 Files Affected:
- (modified) llvm/include/llvm/ADT/APFloat.h (+13)
- (modified) llvm/lib/Analysis/ConstantFolding.cpp (+39-1)
- (added) llvm/test/Transforms/InstCombine/constant-fold-nextafter.ll (+171)
- (added) llvm/test/Transforms/InstCombine/constant-fold-nexttoward-fp128.ll (+187)
- (added) llvm/test/Transforms/InstCombine/constant-fold-nexttoward-ppc-fp128.ll (+187)
- (added) llvm/test/Transforms/InstCombine/constant-fold-nexttoward-x86-fp80.ll (+187)
- (added) llvm/test/Transforms/InstCombine/floating-point-constants.ll (+48)
``````````diff
diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h
index 82ac9a3a1ef80..32e5c1aafc245 100644
--- a/llvm/include/llvm/ADT/APFloat.h
+++ b/llvm/include/llvm/ADT/APFloat.h
@@ -1149,6 +1149,19 @@ class APFloat : public APFloatBase {
/// \param Semantics - type float semantics
LLVM_ABI static APFloat getAllOnesValue(const fltSemantics &Semantics);
+ /// Returns a copy of this APFloat with the requested semantics.
+ /// The requested semantics should be equal to or stronger
+ /// than the semantics of the current instance.
+ APFloat getPromoted(const fltSemantics &Sem) const {
+ assert(isRepresentableBy(this->getSemantics(), Sem) &&
+ "Target semantics will lose information.");
+ APFloat Val(*this);
+ bool LosesInfo;
+ Val.convert(Sem, rmNearestTiesToEven, &LosesInfo);
+ assert(!LosesInfo);
+ return Val;
+ }
+
/// Returns true if the given semantics has actual significand.
///
/// \param Sem - type float semantics
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index da32542cf7870..fadd3e7896c3a 100755
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -1996,7 +1996,9 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
Name == "log10f" || Name == "logb" || Name == "logbf" ||
Name == "log1p" || Name == "log1pf";
case 'n':
- return Name == "nearbyint" || Name == "nearbyintf";
+ return Name == "nearbyint" || Name == "nearbyintf" || Name == "nextafter" ||
+ Name == "nextafterf" || Name == "nexttoward" ||
+ Name == "nexttowardf";
case 'p':
return Name == "pow" || Name == "powf";
case 'r':
@@ -3221,6 +3223,26 @@ static Constant *ConstantFoldLibCall2(StringRef Name, Type *Ty,
if (TLI->has(Func))
return ConstantFoldBinaryFP(atan2, Op1V, Op2V, Ty);
break;
+ case LibFunc_nextafter:
+ case LibFunc_nextafterf:
+ case LibFunc_nexttoward:
+ case LibFunc_nexttowardf:
+ if (TLI->has(Func)) {
+ if (Op1V.isNaN() || Op2V.isNaN()) {
+ return ConstantFP::get(Ty->getContext(),
+ APFloat::getNaN(Ty->getFltSemantics()));
+ }
+
+ APFloat PromotedOp1V = Op1V.getPromoted(APFloat::IEEEquad());
+ APFloat PromotedOp2V = Op2V.getPromoted(APFloat::IEEEquad());
+ if (PromotedOp1V == PromotedOp2V) {
+ return ConstantFP::get(Ty->getContext(), Op1V);
+ }
+
+ APFloat Next(Op1V);
+ Next.next(/*nextDown=*/PromotedOp1V > PromotedOp2V);
+ return ConstantFP::get(Ty->getContext(), Next);
+ }
}
return nullptr;
@@ -4655,6 +4677,22 @@ bool llvm::isMathLibCallNoop(const CallBase *Call,
// may occur, so allow for that possibility.
return !Op0.isZero() || !Op1.isZero();
+ case LibFunc_nextafter:
+ case LibFunc_nextafterf:
+ case LibFunc_nextafterl:
+ case LibFunc_nexttoward:
+ case LibFunc_nexttowardf:
+ case LibFunc_nexttowardl: {
+ APFloat PromotedOp0 = Op0.getPromoted(APFloat::IEEEquad());
+ APFloat PromotedOp1 = Op1.getPromoted(APFloat::IEEEquad());
+ if (PromotedOp0 == PromotedOp1)
+ return true;
+
+ APFloat Next(Op0);
+ Next.next(/*nextDown=*/PromotedOp0 > PromotedOp1);
+ bool DidOverflow = Op0.isLargest() && Next.isInfinity();
+ return !Next.isZero() && !Next.isDenormal() && !DidOverflow;
+ }
default:
break;
}
diff --git a/llvm/test/Transforms/InstCombine/constant-fold-nextafter.ll b/llvm/test/Transforms/InstCombine/constant-fold-nextafter.ll
new file mode 100644
index 0000000000000..9af0a5aeba871
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/constant-fold-nextafter.ll
@@ -0,0 +1,171 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: cat %S/floating-point-constants.ll %s | opt -passes=instcombine -S | FileCheck %s
+
+declare double @nextafter(double noundef, double noundef) #0
+declare float @nextafterf(float noundef, float noundef) #0
+
+attributes #0 = { willreturn memory(errnomem: write) }
+
+; ==================
+; nextafter tests
+; ==================
+
+define double @nextafter_can_constant_fold_up_direction() {
+; CHECK-LABEL: define double @nextafter_can_constant_fold_up_direction() {
+; CHECK-NEXT: ret double 0x3FF0000000000001
+;
+ %next = call double @nextafter(double noundef 1.0, double noundef 2.0)
+ ret double %next
+}
+define double @nextafter_can_constant_fold_down_direction() {
+; CHECK-LABEL: define double @nextafter_can_constant_fold_down_direction() {
+; CHECK-NEXT: ret double 0x3FEFFFFFFFFFFFFF
+;
+ %next = call double @nextafter(double noundef 1.0, double noundef 0.0)
+ ret double %next
+}
+define double @nextafter_can_constant_fold_equal_args() {
+; CHECK-LABEL: define double @nextafter_can_constant_fold_equal_args() {
+; CHECK-NEXT: ret double 1.000000e+00
+;
+ %next = call double @nextafter(double noundef 1.0, double noundef 1.0)
+ ret double %next
+}
+define double @nextafter_can_constant_fold_with_nan_arg() {
+; CHECK-LABEL: define double @nextafter_can_constant_fold_with_nan_arg() {
+; CHECK-NEXT: ret double 0x7FF8000000000000
+;
+ %arg = load double, double* @dbl_nan
+ %next = call double @nextafter(double 1.0, double %arg)
+ ret double %next
+}
+define double @nextafter_not_marked_dead_on_pos_overflow () {
+; CHECK-LABEL: define double @nextafter_not_marked_dead_on_pos_overflow() {
+; CHECK-NEXT: [[NEXT:%.*]] = call double @nextafter(double 0x7FEFFFFFFFFFFFFF, double 0x7FF0000000000000)
+; CHECK-NEXT: ret double 0x7FF0000000000000
+;
+ %arg1 = load double, double* @dbl_pos_max
+ %arg2 = load double, double* @dbl_pos_infinity
+ %next = call double @nextafter(double %arg1, double %arg2)
+ ret double %next
+}
+define double @nextafter_not_marked_dead_on_neg_overflow() {
+; CHECK-LABEL: define double @nextafter_not_marked_dead_on_neg_overflow() {
+; CHECK-NEXT: [[NEXT:%.*]] = call double @nextafter(double 0xFFEFFFFFFFFFFFFF, double 0xFFF0000000000000)
+; CHECK-NEXT: ret double 0xFFF0000000000000
+;
+ %arg1 = load double, double* @dbl_neg_max
+ %arg2 = load double, double* @dbl_neg_infinity
+ %next = call double @nextafter(double %arg1, double %arg2)
+ ret double %next
+}
+define double @nextafter_not_marked_dead_on_zero_from_above() {
+; CHECK-LABEL: define double @nextafter_not_marked_dead_on_zero_from_above() {
+; CHECK-NEXT: [[NEXT:%.*]] = call double @nextafter(double 4.940660e-324, double 0.000000e+00)
+; CHECK-NEXT: ret double 0.000000e+00
+;
+ %arg = load double, double* @dbl_pos_min_subnormal
+ %next = call double @nextafter(double %arg, double 0.0)
+ ret double %next
+}
+define double @nextafter_not_marked_dead_on_zero_from_below() {
+; CHECK-LABEL: define double @nextafter_not_marked_dead_on_zero_from_below() {
+; CHECK-NEXT: [[NEXT:%.*]] = call double @nextafter(double -4.940660e-324, double 0.000000e+00)
+; CHECK-NEXT: ret double -0.000000e+00
+;
+ %arg = load double, double* @dbl_neg_min_subnormal
+ %next = call double @nextafter(double %arg, double 0.0)
+ ret double %next
+}
+define double @nextafter_not_marked_dead_on_subnormal() {
+; CHECK-LABEL: define double @nextafter_not_marked_dead_on_subnormal() {
+; CHECK-NEXT: [[NEXT:%.*]] = call double @nextafter(double 4.940660e-324, double 0x7FF0000000000000)
+; CHECK-NEXT: ret double 9.881310e-324
+;
+ %subnormal = load double, double* @dbl_pos_min_subnormal
+ %infinity = load double, double* @dbl_pos_infinity
+ %next = call double @nextafter(double %subnormal, double %infinity)
+ ret double %next
+}
+
+; ==================
+; nextafterf tests
+; ==================
+
+define float @nextafterf_can_constant_fold_up_direction() {
+; CHECK-LABEL: define float @nextafterf_can_constant_fold_up_direction() {
+; CHECK-NEXT: ret float 0x3FF0000020000000
+;
+ %next = call float @nextafterf(float noundef 1.0, float noundef 2.0)
+ ret float %next
+}
+define float @nextafterf_can_constant_fold_down_direction() {
+; CHECK-LABEL: define float @nextafterf_can_constant_fold_down_direction() {
+; CHECK-NEXT: ret float 0x3FEFFFFFE0000000
+;
+ %next = call float @nextafterf(float noundef 1.0, float noundef 0.0)
+ ret float %next
+}
+define float @nextafterf_can_constant_fold_equal_args() {
+; CHECK-LABEL: define float @nextafterf_can_constant_fold_equal_args() {
+; CHECK-NEXT: ret float 1.000000e+00
+;
+ %next = call float @nextafterf(float noundef 1.0, float noundef 1.0)
+ ret float %next
+}
+define float @nextafterf_can_constant_fold_with_nan_arg() {
+; CHECK-LABEL: define float @nextafterf_can_constant_fold_with_nan_arg() {
+; CHECK-NEXT: ret float 0x7FF8000000000000
+;
+ %arg = load float, float* @flt_nan
+ %next = call float @nextafterf(float 1.0, float %arg)
+ ret float %next
+}
+define float @nextafterf_not_marked_dead_on_pos_overflow() {
+; CHECK-LABEL: define float @nextafterf_not_marked_dead_on_pos_overflow() {
+; CHECK-NEXT: [[NEXT:%.*]] = call float @nextafterf(float 0x47EFFFFFE0000000, float 0x7FF0000000000000)
+; CHECK-NEXT: ret float 0x7FF0000000000000
+;
+ %arg1 = load float, float* @flt_pos_max
+ %arg2 = load float, float* @flt_pos_infinity
+ %next = call float @nextafterf(float %arg1, float %arg2)
+ ret float %next
+}
+define float @nextafterf_not_marked_dead_on_neg_overflow() {
+; CHECK-LABEL: define float @nextafterf_not_marked_dead_on_neg_overflow() {
+; CHECK-NEXT: [[NEXT:%.*]] = call float @nextafterf(float 0xC7EFFFFFE0000000, float 0xFFF0000000000000)
+; CHECK-NEXT: ret float 0xFFF0000000000000
+;
+ %arg1 = load float, float* @flt_neg_max
+ %arg2 = load float, float* @flt_neg_infinity
+ %next = call float @nextafterf(float %arg1, float %arg2)
+ ret float %next
+}
+define float @nextafterf_not_marked_dead_on_zero_from_above() {
+; CHECK-LABEL: define float @nextafterf_not_marked_dead_on_zero_from_above() {
+; CHECK-NEXT: [[NEXT:%.*]] = call float @nextafterf(float 0x36A0000000000000, float 0.000000e+00)
+; CHECK-NEXT: ret float 0.000000e+00
+;
+ %arg = load float, float* @flt_pos_min_subnormal
+ %next = call float @nextafterf(float %arg, float 0.0)
+ ret float %next
+}
+define float @nextafterf_not_marked_dead_on_zero_from_below() {
+; CHECK-LABEL: define float @nextafterf_not_marked_dead_on_zero_from_below() {
+; CHECK-NEXT: [[NEXT:%.*]] = call float @nextafterf(float 0xB6A0000000000000, float 0.000000e+00)
+; CHECK-NEXT: ret float -0.000000e+00
+;
+ %arg = load float, float* @flt_neg_min_subnormal
+ %next = call float @nextafterf(float %arg, float 0.0)
+ ret float %next
+}
+define float @nextafterf_not_marked_dead_on_subnormal() {
+; CHECK-LABEL: define float @nextafterf_not_marked_dead_on_subnormal() {
+; CHECK-NEXT: [[NEXT:%.*]] = call float @nextafterf(float 0x36A0000000000000, float 0x7FF0000000000000)
+; CHECK-NEXT: ret float 0x36B0000000000000
+;
+ %subnormal = load float, float* @flt_pos_min_subnormal
+ %infinity = load float, float* @flt_pos_infinity
+ %next = call float @nextafterf(float %subnormal, float %infinity)
+ ret float %next
+}
diff --git a/llvm/test/Transforms/InstCombine/constant-fold-nexttoward-fp128.ll b/llvm/test/Transforms/InstCombine/constant-fold-nexttoward-fp128.ll
new file mode 100644
index 0000000000000..5f044241fbce8
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/constant-fold-nexttoward-fp128.ll
@@ -0,0 +1,187 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: cat %S/floating-point-constants.ll %s | opt -passes=instcombine -S | FileCheck %s
+
+declare double @nexttoward(double noundef, fp128 noundef) #0
+declare float @nexttowardf(float noundef, fp128 noundef) #0
+
+attributes #0 = { willreturn memory(errnomem: write) }
+
+; ==================
+; nexttoward tests
+; ==================
+
+define double @nexttoward_can_constant_fold_up_direction() {
+; CHECK-LABEL: define double @nexttoward_can_constant_fold_up_direction() {
+; CHECK-NEXT: ret double 0x3FF0000000000001
+;
+ %arg = fpext double 2.0 to fp128
+ %next = call double @nexttoward(double noundef 1.0, fp128 %arg)
+ ret double %next
+}
+define double @nexttoward_can_constant_fold_down_direction() {
+; CHECK-LABEL: define double @nexttoward_can_constant_fold_down_direction() {
+; CHECK-NEXT: ret double 0x3FEFFFFFFFFFFFFF
+;
+ %arg = fpext double 0.0 to fp128
+ %next = call double @nexttoward(double noundef 1.0, fp128 %arg)
+ ret double %next
+}
+define double @nexttoward_can_constant_fold_equal_args() {
+; CHECK-LABEL: define double @nexttoward_can_constant_fold_equal_args() {
+; CHECK-NEXT: ret double 1.000000e+00
+;
+ %arg = fpext double 1.0 to fp128
+ %next = call double @nexttoward(double 1.0, fp128 %arg)
+ ret double %next
+}
+define double @nexttoward_can_constant_fold_with_nan_arg() {
+; CHECK-LABEL: define double @nexttoward_can_constant_fold_with_nan_arg() {
+; CHECK-NEXT: ret double 0x7FF8000000000000
+;
+ %nan = load double, double* @dbl_nan
+ %arg = fpext double %nan to fp128
+ %next = call double @nexttoward(double 1.0, fp128 %arg)
+ ret double %next
+}
+define double @nexttoward_not_marked_dead_on_pos_overflow() {
+; CHECK-LABEL: define double @nexttoward_not_marked_dead_on_pos_overflow() {
+; CHECK-NEXT: [[NEXT:%.*]] = call double @nexttoward(double 0x7FEFFFFFFFFFFFFF, fp128 0xL00000000000000007FFF000000000000)
+; CHECK-NEXT: ret double 0x7FF0000000000000
+;
+ %pos_max = load double, double* @dbl_pos_max
+ %pos_inf = load double, double* @dbl_pos_infinity
+ %ext_pos_inf = fpext double %pos_inf to fp128
+ %next = call double @nexttoward(double %pos_max, fp128 %ext_pos_inf)
+ ret double %next
+}
+define double @nexttoward_not_marked_dead_on_neg_overflow() {
+; CHECK-LABEL: define double @nexttoward_not_marked_dead_on_neg_overflow() {
+; CHECK-NEXT: [[NEXT:%.*]] = call double @nexttoward(double 0xFFEFFFFFFFFFFFFF, fp128 0xL0000000000000000FFFF000000000000)
+; CHECK-NEXT: ret double 0xFFF0000000000000
+;
+ %neg_max = load double, double* @dbl_neg_max
+ %neg_inf = load double, double* @dbl_neg_infinity
+ %ext_neg_inf = fpext double %neg_inf to fp128
+ %next = call double @nexttoward(double %neg_max, fp128 %ext_neg_inf)
+ ret double %next
+}
+define double @nexttoward_not_marked_dead_on_zero_from_above() {
+; CHECK-LABEL: define double @nexttoward_not_marked_dead_on_zero_from_above() {
+; CHECK-NEXT: [[NEXT:%.*]] = call double @nexttoward(double 4.940660e-324, fp128 0xL00000000000000000000000000000000)
+; CHECK-NEXT: ret double 0.000000e+00
+;
+ %subnormal = load double, double* @dbl_pos_min_subnormal
+ %zero = fpext double 0.0 to fp128
+ %next = call double @nexttoward(double %subnormal, fp128 %zero)
+ ret double %next
+}
+define double @nexttoward_not_marked_dead_on_zero_from_below() {
+; CHECK-LABEL: define double @nexttoward_not_marked_dead_on_zero_from_below() {
+; CHECK-NEXT: [[NEXT:%.*]] = call double @nexttoward(double -4.940660e-324, fp128 0xL00000000000000000000000000000000)
+; CHECK-NEXT: ret double -0.000000e+00
+;
+ %subnormal = load double, double* @dbl_neg_min_subnormal
+ %zero = fpext double 0.0 to fp128
+ %next = call double @nexttoward(double %subnormal, fp128 %zero)
+ ret double %next
+}
+define double @nexttoward_not_marked_dead_on_subnormal() {
+; CHECK-LABEL: define double @nexttoward_not_marked_dead_on_subnormal() {
+; CHECK-NEXT: [[NEXT:%.*]] = call double @nexttoward(double 4.940660e-324, fp128 0xL00000000000000003FFF000000000000)
+; CHECK-NEXT: ret double 9.881310e-324
+;
+ %subnormal = load double, double* @dbl_pos_min_subnormal
+ %target = fpext double 1.0 to fp128
+ %next = call double @nexttoward(double %subnormal, fp128 %target)
+ ret double %next
+}
+
+; ==================
+; nexttowardf tests
+; ==================
+
+define float @nexttowardf_can_constant_fold_up_direction() {
+; CHECK-LABEL: define float @nexttowardf_can_constant_fold_up_direction() {
+; CHECK-NEXT: ret float 0x3FF0000020000000
+;
+ %arg = fpext float 2.0 to fp128
+ %next = call float @nexttowardf(float noundef 1.0, fp128 %arg)
+ ret float %next
+}
+define float @nexttowardf_can_constant_fold_down_direction() {
+; CHECK-LABEL: define float @nexttowardf_can_constant_fold_down_direction() {
+; CHECK-NEXT: ret float 0x3FEFFFFFE0000000
+;
+ %arg = fpext float 0.0 to fp128
+ %next = call float @nexttowardf(float noundef 1.0, fp128 %arg)
+ ret float %next
+}
+define float @nexttowardf_can_constant_fold_equal_args() {
+; CHECK-LABEL: define float @nexttowardf_can_constant_fold_equal_args() {
+; CHECK-NEXT: ret float 1.000000e+00
+;
+ %arg = fpext float 1.0 to fp128
+ %next = call float @nexttowardf(float 1.0, fp128 %arg)
+ ret float %next
+}
+define float @nexttowardf_can_constant_fold_with_nan_arg() {
+; CHECK-LABEL: define float @nexttowardf_can_constant_fold_with_nan_arg() {
+; CHECK-NEXT: ret float 0x7FF8000000000000
+;
+ %nan = load float, float* @flt_nan
+ %ext_nan = fpext float %nan to fp128
+ %next = call float @nexttowardf(float 1.0, fp128 %ext_nan)
+ ret float %next
+}
+define float @nexttowardf_not_marked_dead_on_pos_overflow () {
+; CHECK-LABEL: define float @nexttowardf_not_marked_dead_on_pos_overflow() {
+; CHECK-NEXT: [[NEXT:%.*]] = call float @nexttowardf(float 0x47EFFFFFE0000000, fp128 0xL00000000000000007FFF000000000000)
+; CHECK-NEXT: ret float 0x7FF0000000000000
+;
+ %pos_max = load float, float* @flt_pos_max
+ %pos_inf = load float, float* @flt_pos_infinity
+ %ext_pos_inf = fpext float %pos_inf to fp128
+ %next = call float @nexttowardf(float %pos_max, fp128 %ext_pos_inf)
+ ret float %next
+}
+define float @nexttowardf_not_marked_dead_on_neg_overflow() {
+; CHECK-LABEL: define float @nexttowardf_not_marked_dead_on_neg_overflow() {
+; CHECK-NEXT: [[NEXT:%.*]] = call float @nexttowardf(float 0xC7EFFFFFE0000000, fp128 0xL0000000000000000FFFF000000000000)
+; CHECK-NEXT: ret float 0xFFF0000000000000
+;
+ %neg_max = load float, float* @flt_neg_max
+ %neg_inf = load float, float* @flt_neg_infinity
+ %ext_neg_inf = fpext float %neg_inf to fp128
+ %next = call float @nexttowardf(float %neg_max, fp128 %ext_neg_inf)
+ ret float %next
+}
+define float @nexttowardf_not_marked_dead_on_zero_from_above() {
+; CHECK-LABEL: define float @nexttowardf_not_marked_dead_on_zero_from_above() {
+; CHECK-NEXT: [[NEXT:%.*]] = call float @nexttowardf(float 0x36A0000000000000, fp128 0xL00000000000000000000000000000000)
+; CHECK-NEXT: ret float 0.000000e+00
+;
+ %min_subnormal = load float, float* @flt_pos_min_subnormal
+ %zero = fpext float 0.0 to fp128
+ %next = call float @nexttowardf(float %min_subnormal, fp128 %zero)
+ ret float %next
+}
+define float @nexttowardf_not_marked_dead_on_zero_from_below() {
+; CHECK-LABEL: define float @nexttowardf_not_marked_dead_on_zero_from_below() {
+; CHECK-NEXT: [[NEXT:%.*]] = call float @nexttowardf(float 0xB6A0000000000000, fp128 0xL00000000000000000000000000000000)
+; CHECK-NEXT: ret float -0.000000e+00
+;
+ %min_subnormal = load float, float* @flt_neg_min_subnormal
+ %zero = fpext float 0.0 to fp128
+ %next = call float @nexttowardf(float %min_subnormal, fp128 %zero)
+ ret float %next
+}
+define float @nexttowardf_not_marked_dead_on_subnormal() {
+; CHECK-LABEL: define float @nexttowardf_not_marked_dead_on_subnormal() {
+; CHECK-NEXT: [[NEXT:%.*]] = call float @nexttowardf(float 0x36A0000000000000, fp128 0xL00000000000000003FFF000000000000)
+; CHECK-NEXT: ret float 0x36B0000000000000
+;
+ %subnormal = load float, float* @flt_pos_min_subnormal
+ %target = fpext float 1.0 to fp128
+ %next = call float @nexttowardf(float %subnormal, fp128 %target)
+ ret float %next
+}
diff --git a/llvm/test/Transforms/InstCombine/constant-fold-nexttoward-ppc-fp128.ll b/llvm/test/Transforms/InstCombine/constant-fold-nexttoward-ppc-fp128.ll
new file mode 100644
index 0000000000000..30da81b1bd01f
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/constant-fold-nexttoward-ppc-fp128.ll
@@ -0,0 +1,187 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: cat %S/floating-point-constants.ll %s | opt -passes=instcombine -S | FileCheck %s
+
+declare double @nexttoward(double noundef, ppc_fp128 noundef) #0
+declare float @nexttowardf(float noundef, ppc_fp128 noundef) #0
+
+attribut...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/167324
More information about the llvm-commits
mailing list