From 075eb2475703b84e9468b9e081a9e764e636511a Mon Sep 17 00:00:00 2001 From: Soham Panda Date: Mon, 10 Aug 2026 16:47:45 -0500 Subject: [PATCH] [BugFix][Arith] Fold float Min/Max commutatively on NaN TryConstFold/ use std::min/std::max on the float-constant branch. Those are defined as a < b ? b : a, and every comparison against NaN is false, so the result depends on argument order: max(1.0, nan) folds to 1.0 while max(nan, 1.0) folds to nan. The same expression is order-independent once the operands are not compile-time constants, because the runtime lowers to fmaxf/fminf. The fold therefore disagrees with the runtime path and with itself under operand swap. Use std::fmax/std::fmin on the float branch so the fold matches the runtime semantics and returns the non-NaN operand either way. The integer branch is unchanged, as integers have no NaN. is already included. --- src/arith/const_fold.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/arith/const_fold.h b/src/arith/const_fold.h index 91db540f2e82..e51dc6b7e86d 100644 --- a/src/arith/const_fold.h +++ b/src/arith/const_fold.h @@ -330,7 +330,7 @@ inline ffi::Optional TryConstFold(PrimExpr a, PrimExpr b) { TVM_ARITH_CONST_PROPAGATION({ const DataType& rtype = a.dtype(); if (pa && pb) return IntImm(rtype, std::min(pa->value, pb->value)); - if (fa && fb) return FloatImm(rtype, std::min(fa->value, fb->value)); + if (fa && fb) return FloatImm(rtype, std::fmin(fa->value, fb->value)); }); if (a.same_as(b)) return a; return std::nullopt; @@ -341,7 +341,7 @@ inline ffi::Optional TryConstFold(PrimExpr a, PrimExpr b) { TVM_ARITH_CONST_PROPAGATION({ const DataType& rtype = a.dtype(); if (pa && pb) return IntImm(rtype, std::max(pa->value, pb->value)); - if (fa && fb) return FloatImm(rtype, std::max(fa->value, fb->value)); + if (fa && fb) return FloatImm(rtype, std::fmax(fa->value, fb->value)); }); if (a.same_as(b)) return a; return std::nullopt;