https://github.com/byteforge38 updated https://github.com/llvm/llvm-project/pull/178421
>From 28085bfb3dde9dd5b6c954b49bea7554cad3a74f Mon Sep 17 00:00:00 2001 From: byteforge38 <[email protected]> Date: Wed, 28 Jan 2026 07:45:17 -0600 Subject: [PATCH] [clang][constexpr] Move inf/nan/denormal handling into FP binop callbacks --- clang/lib/AST/ByteCode/InterpBuiltin.cpp | 22 +++++++++++++++------- clang/lib/AST/ExprConstant.cpp | 22 +++++++++++++++------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 4cf6898df3692..fb7c51608f85b 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -2482,8 +2482,8 @@ static bool interp__builtin_elementwise_int_unaryop( static bool interp__builtin_elementwise_fp_binop( InterpState &S, CodePtr OpPC, const CallExpr *Call, - llvm::function_ref<APFloat(const APFloat &, const APFloat &, - std::optional<APSInt> RoundingMode)> + llvm::function_ref<std::optional<APFloat>( + const APFloat &, const APFloat &, std::optional<APSInt> RoundingMode)> Fn) { assert((Call->getNumArgs() == 2) || (Call->getNumArgs() == 3)); const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>(); @@ -2509,10 +2509,10 @@ static bool interp__builtin_elementwise_fp_binop( using T = PrimConv<PT_Float>::T; APFloat ElemA = APtr.elem<T>(ElemIdx).getAPFloat(); APFloat ElemB = BPtr.elem<T>(ElemIdx).getAPFloat(); - if (ElemA.isNaN() || ElemA.isInfinity() || ElemA.isDenormal() || - ElemB.isNaN() || ElemB.isInfinity() || ElemB.isDenormal()) + std::optional<APFloat> Result = Fn(ElemA, ElemB, RoundingMode); + if (!Result) return false; - Dst.elem<T>(ElemIdx) = static_cast<T>(Fn(ElemA, ElemB, RoundingMode)); + Dst.elem<T>(ElemIdx) = static_cast<T>(*Result); } Dst.initializeAllElements(); @@ -5822,7 +5822,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, case clang::X86::BI__builtin_ia32_minph512: return interp__builtin_elementwise_fp_binop( S, OpPC, Call, - [](const APFloat &A, const APFloat &B, std::optional<APSInt>) { + [](const APFloat &A, const APFloat &B, + std::optional<APSInt>) -> std::optional<APFloat> { + if (A.isNaN() || A.isInfinity() || A.isDenormal() || B.isNaN() || + B.isInfinity() || B.isDenormal()) + return std::nullopt; if (A.isZero() && B.isZero()) return B; return llvm::minimum(A, B); @@ -5839,7 +5843,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, case clang::X86::BI__builtin_ia32_maxph512: return interp__builtin_elementwise_fp_binop( S, OpPC, Call, - [](const APFloat &A, const APFloat &B, std::optional<APSInt>) { + [](const APFloat &A, const APFloat &B, + std::optional<APSInt>) -> std::optional<APFloat> { + if (A.isNaN() || A.isInfinity() || A.isDenormal() || B.isNaN() || + B.isInfinity() || B.isDenormal()) + return std::nullopt; if (A.isZero() && B.isZero()) return B; return llvm::maximum(A, B); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 58748fa5ba49b..73768f7dd612b 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -12277,8 +12277,8 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) { }; auto EvaluateFpBinOpExpr = - [&](llvm::function_ref<APFloat(const APFloat &, const APFloat &, - std::optional<APSInt>)> + [&](llvm::function_ref<std::optional<APFloat>( + const APFloat &, const APFloat &, std::optional<APSInt>)> Fn) { assert(E->getNumArgs() == 2 || E->getNumArgs() == 3); APValue A, B; @@ -12304,10 +12304,10 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) { for (unsigned EltNum = 0; EltNum < NumElems; ++EltNum) { const APFloat &EltA = A.getVectorElt(EltNum).getFloat(); const APFloat &EltB = B.getVectorElt(EltNum).getFloat(); - if (EltA.isNaN() || EltA.isInfinity() || EltA.isDenormal() || - EltB.isNaN() || EltB.isInfinity() || EltB.isDenormal()) + std::optional<APFloat> Result = Fn(EltA, EltB, RoundingMode); + if (!Result) return false; - ResultElements.push_back(APValue(Fn(EltA, EltB, RoundingMode))); + ResultElements.push_back(APValue(*Result)); } return Success(APValue(ResultElements.data(), NumElems), E); }; @@ -14385,7 +14385,11 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) { case clang::X86::BI__builtin_ia32_minph256: case clang::X86::BI__builtin_ia32_minph512: return EvaluateFpBinOpExpr( - [](const APFloat &A, const APFloat &B, std::optional<APSInt>) { + [](const APFloat &A, const APFloat &B, + std::optional<APSInt>) -> std::optional<APFloat> { + if (A.isNaN() || A.isInfinity() || A.isDenormal() || B.isNaN() || + B.isInfinity() || B.isDenormal()) + return std::nullopt; if (A.isZero() && B.isZero()) return B; return llvm::minimum(A, B); @@ -14401,7 +14405,11 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) { case clang::X86::BI__builtin_ia32_maxph256: case clang::X86::BI__builtin_ia32_maxph512: return EvaluateFpBinOpExpr( - [](const APFloat &A, const APFloat &B, std::optional<APSInt>) { + [](const APFloat &A, const APFloat &B, + std::optional<APSInt>) -> std::optional<APFloat> { + if (A.isNaN() || A.isInfinity() || A.isDenormal() || B.isNaN() || + B.isInfinity() || B.isDenormal()) + return std::nullopt; if (A.isZero() && B.isZero()) return B; return llvm::maximum(A, B); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
