-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[ConstantFolding] Constant fold nextafter and nexttoward #168794
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
2a6ad7f to
ea98d6b
Compare
|
Note that this is a second try of this PR. I closed it because I realized I unnecessarily touched some Some notes:
|
|
@llvm/pr-subscribers-llvm-analysis @llvm/pr-subscribers-llvm-transforms Author: Sayan Sivakumaran (sivakusayan) ChangesFixes issue #74368. This patch enables us to constant fold Patch is 33.76 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/168794.diff 6 Files Affected:
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 4bece85d3cfbf..e0aaea2569334 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -2008,7 +2008,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':
@@ -3174,6 +3176,53 @@ static Constant *evaluateCompare(const APFloat &Op1, const APFloat &Op2,
return nullptr;
}
+/// Returns the first NaN in the operand list if it exists, preserving the NaN
+/// payload if possible. Returns nullptr if no NaNs are in the list.
+static Constant *TryConstantFoldNaN(ArrayRef<APFloat> Operands,
+ const Type *RetTy) {
+ assert(RetTy != nullptr);
+ for (const APFloat &Op : Operands) {
+ if (Op.isNaN()) {
+ bool Unused;
+ APFloat Ret(Op);
+ Ret.convert(RetTy->getFltSemantics(), detail::rmNearestTiesToEven,
+ &Unused);
+ return ConstantFP::get(RetTy->getContext(), Ret);
+ }
+ }
+ return nullptr;
+}
+
+static Constant *ConstantFoldNextToward(const APFloat &Op0, const APFloat &Op1,
+ const Type *RetTy,
+ bool *WouldSetErrno) {
+ assert(RetTy != nullptr);
+ *WouldSetErrno = false;
+
+ Constant *RetNaN = TryConstantFoldNaN({Op0, Op1}, RetTy);
+ if (RetNaN != nullptr) {
+ return RetNaN;
+ }
+
+ // Recall that the second argument of nexttoward is always a long double,
+ // so we may need to promote the first argument for comparisons to be valid.
+ bool LosesInfo;
+ APFloat PromotedOp0(Op0);
+ PromotedOp0.convert(Op1.getSemantics(), detail::rmNearestTiesToEven,
+ &LosesInfo);
+ assert(!LosesInfo && "Unexpected lossy promotion");
+
+ if (PromotedOp0 == Op1)
+ return ConstantFP::get(RetTy->getContext(), Op0);
+
+ APFloat Next(Op0);
+ Next.next(/*nextDown=*/PromotedOp0 > Op1);
+ const bool DidOverflow = !Op0.isInfinity() && Next.isInfinity();
+ *WouldSetErrno = Next.isZero() || Next.isDenormal() || DidOverflow;
+
+ return ConstantFP::get(RetTy->getContext(), Next);
+}
+
static Constant *ConstantFoldLibCall2(StringRef Name, Type *Ty,
ArrayRef<Constant *> Operands,
const TargetLibraryInfo *TLI) {
@@ -3233,6 +3282,14 @@ 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)) {
+ bool Unused;
+ return ConstantFoldNextToward(Op1V, Op2V, Ty, &Unused);
+ }
}
return nullptr;
@@ -4685,6 +4742,16 @@ 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: {
+ bool WouldSetErrno;
+ ConstantFoldNextToward(Op0, Op1, F->getReturnType(), &WouldSetErrno);
+ return !WouldSetErrno;
+ }
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..1650a71d872b5
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/constant-fold-nextafter.ll
@@ -0,0 +1,226 @@
+; 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, double) #0
+declare float @nextafterf(float, float) #0
+
+attributes #0 = { willreturn memory(errnomem: write) }
+
+define double @nextafter_up_direction() {
+; CHECK-LABEL: define double @nextafter_up_direction() {
+; CHECK-NEXT: ret double 0x3FF0000000000001
+;
+ %next = call double @nextafter(double 1.0, double 2.0)
+ ret double %next
+}
+
+define float @nextafterf_up_direction() {
+; CHECK-LABEL: define float @nextafterf_up_direction() {
+; CHECK-NEXT: ret float 0x3FF0000020000000
+;
+ %next = call float @nextafterf(float 1.0, float 2.0)
+ ret float %next
+}
+
+define double @nextafter_down_direction() {
+; CHECK-LABEL: define double @nextafter_down_direction() {
+; CHECK-NEXT: ret double 0x3FEFFFFFFFFFFFFF
+;
+ %next = call double @nextafter(double 1.0, double 0.0)
+ ret double %next
+}
+
+define float @nextafterf_down_direction() {
+; CHECK-LABEL: define float @nextafterf_down_direction() {
+; CHECK-NEXT: ret float 0x3FEFFFFFE0000000
+;
+ %next = call float @nextafterf(float 1.0, float 0.0)
+ ret float %next
+}
+
+define double @nextafter_equal_args() {
+; CHECK-LABEL: define double @nextafter_equal_args() {
+; CHECK-NEXT: ret double 1.000000e+00
+;
+ %next = call double @nextafter(double 1.0, double 1.0)
+ ret double %next
+}
+
+define float @nextafterf_equal_args() {
+; CHECK-LABEL: define float @nextafterf_equal_args() {
+; CHECK-NEXT: ret float 1.000000e+00
+;
+ %next = call float @nextafterf(float 1.0, float 1.0)
+ ret float %next
+}
+
+define double @nextafter_nan_with_payload() {
+; CHECK-LABEL: define double @nextafter_nan_with_payload() {
+; CHECK-NEXT: ret double 0x7FF8000000000001
+;
+ %nan = load double, double* @dbl_nan
+ %tmp1 = bitcast double %nan to i64
+ %tmp2 = or i64 %tmp1, 1
+ %nan_with_payload = bitcast i64 %tmp2 to double
+ %next = call double @nextafter(double %nan_with_payload, double 1.0)
+ ret double %next
+
+}
+
+define float @nextafterf_nan_with_payload() {
+; CHECK-LABEL: define float @nextafterf_nan_with_payload() {
+; CHECK-NEXT: ret float 0x7FF8000020000000
+;
+ %nan = load float, float* @flt_nan
+ %tmp1 = bitcast float %nan to i32
+ %tmp2 = or i32 %tmp1, 1
+ %nan_with_payload = bitcast i32 %tmp2 to float
+ %next = call float @nextafterf(float %nan_with_payload, float 1.0)
+ ret float %next
+}
+
+define double @nextafter_pos_overflow () {
+; CHECK-LABEL: define double @nextafter_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 float @nextafterf_pos_overflow() {
+; CHECK-LABEL: define float @nextafterf_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 double @nextafter_neg_overflow() {
+; CHECK-LABEL: define double @nextafter_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 float @nextafterf_neg_overflow() {
+; CHECK-LABEL: define float @nextafterf_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 double @nextafter_zero_from_above() {
+; CHECK-LABEL: define double @nextafter_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 float @nextafterf_zero_from_above() {
+; CHECK-LABEL: define float @nextafterf_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 double @nextafter_zero_from_below() {
+; CHECK-LABEL: define double @nextafter_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 float @nextafterf_zero_from_below() {
+; CHECK-LABEL: define float @nextafterf_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 double @nextafter_subnormal() {
+; CHECK-LABEL: define double @nextafter_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
+}
+
+define float @nextafterf_subnormal() {
+; CHECK-LABEL: define float @nextafterf_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
+}
+
+define double @nextafter_poison() {
+; CHECK-LABEL: define double @nextafter_poison() {
+; CHECK-NEXT: [[NEXT:%.*]] = call double @nextafter(double poison, double 1.000000e+00)
+; CHECK-NEXT: ret double [[NEXT]]
+;
+ %next = call double @nextafter(double poison, double 1.0)
+ ret double %next
+}
+
+define double @nextafterf_poison() {
+; CHECK-LABEL: define double @nextafterf_poison() {
+; CHECK-NEXT: [[NEXT:%.*]] = call double @nextafterf(float poison, float 1.000000e+00)
+; CHECK-NEXT: ret double [[NEXT]]
+;
+ %next = call double @nextafterf(float poison, float 1.0)
+ ret double %next
+}
+
+define double @nextafter_subnormal_readnone() {
+; CHECK-LABEL: define double @nextafter_subnormal_readnone() {
+; CHECK-NEXT: [[NEXT:%.*]] = call double @nextafter(double 4.940660e-324, double 0x7FF0000000000000) #[[ATTR1:[0-9]+]]
+; 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) readnone
+ ret double %next
+}
+
+define float @nextafterf_subnormal_readnone() {
+; CHECK-LABEL: define float @nextafterf_subnormal_readnone() {
+; CHECK-NEXT: [[NEXT:%.*]] = call float @nextafterf(float 0x36A0000000000000, float 0x7FF0000000000000) #[[ATTR1]]
+; 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) readnone
+ 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..577ea0c1b3fba
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/constant-fold-nexttoward-fp128.ll
@@ -0,0 +1,243 @@
+; 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, fp128) #0
+declare float @nexttowardf(float, fp128) #0
+
+attributes #0 = { willreturn memory(errnomem: write) }
+
+define double @nexttoward_up_direction() {
+; CHECK-LABEL: define double @nexttoward_up_direction() {
+; CHECK-NEXT: ret double 0x3FF0000000000001
+;
+ %arg = fpext double 2.0 to fp128
+ %next = call double @nexttoward(double 1.0, fp128 %arg)
+ ret double %next
+}
+
+define float @nexttowardf_up_direction() {
+; CHECK-LABEL: define float @nexttowardf_up_direction() {
+; CHECK-NEXT: ret float 0x3FF0000020000000
+;
+ %arg = fpext float 2.0 to fp128
+ %next = call float @nexttowardf(float 1.0, fp128 %arg)
+ ret float %next
+}
+
+define double @nexttoward_down_direction() {
+; CHECK-LABEL: define double @nexttoward_down_direction() {
+; CHECK-NEXT: ret double 0x3FEFFFFFFFFFFFFF
+;
+ %arg = fpext double 0.0 to fp128
+ %next = call double @nexttoward(double 1.0, fp128 %arg)
+ ret double %next
+}
+
+define float @nexttowardf_down_direction() {
+; CHECK-LABEL: define float @nexttowardf_down_direction() {
+; CHECK-NEXT: ret float 0x3FEFFFFFE0000000
+;
+ %arg = fpext float 0.0 to fp128
+ %next = call float @nexttowardf(float 1.0, fp128 %arg)
+ ret float %next
+}
+
+define double @nexttoward_equal_args() {
+; CHECK-LABEL: define double @nexttoward_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 float @nexttowardf_equal_args() {
+; CHECK-LABEL: define float @nexttowardf_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 double @nexttoward_nan_with_payload() {
+; CHECK-LABEL: define double @nexttoward_nan_with_payload() {
+; CHECK-NEXT: ret double 0x7FF8000000000001
+;
+ %nan = load double, double* @dbl_nan
+ %tmp1 = bitcast double %nan to i64
+ %tmp2 = or i64 %tmp1, 1
+ %nan_with_payload = bitcast i64 %tmp2 to double
+ %dummy_arg = fpext double 1.0 to fp128
+ %next = call double @nexttoward(double %nan_with_payload, fp128 %dummy_arg)
+ ret double %next
+}
+
+define float @nexttowardf_nan_with_payload() {
+; CHECK-LABEL: define float @nexttowardf_nan_with_payload() {
+; CHECK-NEXT: ret float 0x7FF8000020000000
+;
+ %nan = load float, float* @flt_nan
+ %tmp1 = bitcast float %nan to i32
+ %tmp2 = or i32 %tmp1, 1
+ %nan_with_payload = bitcast i32 %tmp2 to float
+ %dummy_arg = fpext float 1.0 to fp128
+ %next = call float @nexttowardf(float %nan_with_payload, fp128 %dummy_arg)
+ ret float %next
+}
+
+define double @nexttoward_pos_overflow() {
+; CHECK-LABEL: define double @nexttoward_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 float @nexttowardf_pos_overflow () {
+; CHECK-LABEL: define float @nexttowardf_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 double @nexttoward_neg_overflow() {
+; CHECK-LABEL: define double @nexttoward_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 float @nexttowardf_neg_overflow() {
+; CHECK-LABEL: define float @nexttowardf_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 double @nexttoward_zero_from_above() {
+; CHECK-LABEL: define double @nexttoward_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 float @nexttowardf_zero_from_above() {
+; CHECK-LABEL: define float @nexttowardf_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 double @nexttoward_zero_from_below() {
+; CHECK-LABEL: define double @nexttoward_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 float @nexttowardf_zero_from_below() {
+; CHECK-LABEL: define float @nexttowardf_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 double @nexttoward_subnormal() {
+; CHECK-LABEL: define double @nexttoward_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
+}
+
+define float @nexttowardf_subnormal() {
+; CHECK-LABEL: define float @nexttowardf_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...
[truncated]
|
🐧 Linux x64 Test Results
|
You can use this format. |
| ; CHECK-LABEL: define double @nexttoward_nan_with_payload() { | ||
| ; CHECK-NEXT: ret double 0x7FF8000000000001 | ||
| ; | ||
| %nan = load double, double* @dbl_nan |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| %nan = load double, double* @dbl_nan | |
| %nan = load double, ptr @dbl_nan |
Use opaque pointer type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thanks. Also slightly simplified the nan_with_payload test since the intermediary bitcast is no longer needed.
| @@ -0,0 +1,256 @@ | |||
| ; 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 | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| ; RUN: cat %S/floating-point-constants.ll %s | opt -passes=instcombine -S | FileCheck %s | |
| ; RUN: opt -S -passes=instcombine < %s | FileCheck %s |
There's no reason to use cat in tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did it that way so I didn't have to copy-paste floating point constants everywhere, and could instead pull in the values from the floating-point-constants.ll file. I couldn't really find an established pattern for it, so I asked for suggestions in the LLVM Discord. Do you know of a better way to do this?
If it feels too strange, I could copy what other lit tests do. I see other tests like ilogb folding hardcode the constants for example.
| declare double @nextafter(double, double) #0 | ||
| declare float @nextafterf(float, float) #0 | ||
|
|
||
| attributes #0 = { willreturn memory(errnomem: write) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this to the end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
|
I'm a bit confused why the Build CI Checks passed but the I did a full rebuild locally after clearing my cache and everything seems fine. Assuming I'm not misunderstanding, could someone restart the |
Closes #74368.
This patch enables us to constant fold
nextafterandnexttowardas long as we know thaterrnowon't be written. In the latter case, we should keep the function call so the programmer can observe the side effect.