[llvm] [ConstantFolding] Constant fold nextafter and nexttoward (PR #168794)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 23 05:03:36 PST 2025


================
@@ -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)
----------------
dtcxzyw wrote:

Use `APFloat::compare` to save one comparison. 

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


More information about the llvm-commits mailing list