[Mlir-commits] [mlir] bd05e1b - [mlir][arith] Fix crash when constant-folding truncf of inf to FiniteOnly float type (#186191)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Thu Mar 12 11:54:58 PDT 2026


Author: Mehdi Amini
Date: 2026-03-12T19:54:53+01:00
New Revision: bd05e1bca82d0e0ba0d7f75dd09f8c7d995dbafd

URL: https://github.com/llvm/llvm-project/commit/bd05e1bca82d0e0ba0d7f75dd09f8c7d995dbafd
DIFF: https://github.com/llvm/llvm-project/commit/bd05e1bca82d0e0ba0d7f75dd09f8c7d995dbafd.diff

LOG: [mlir][arith] Fix crash when constant-folding truncf of inf to FiniteOnly float type (#186191)

When arith.truncf constant-folding converts a value such as infinity to
a type with fltNonfiniteBehavior::FiniteOnly (e.g. f4E2M1FN),
APFloat::convert hits an llvm_unreachable("semantics don't support
inf\!").

The fix adds early-exit guards in convertFloatValue() to return
failure() before calling APFloat::convert() when the source value is
infinity or NaN and the target type cannot represent it. This makes the
fold a no-op for unrepresentable special values, matching the existing
behavior for lossy ordinary conversions.

Fixes #185351

Assisted-by: Claude Code

Added: 
    

Modified: 
    mlir/lib/Dialect/Arith/IR/ArithOps.cpp
    mlir/test/Dialect/Arith/canonicalize.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp
index 6f368604df65a..d6a98a667da32 100644
--- a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp
+++ b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp
@@ -1451,6 +1451,17 @@ static bool checkWidthChangeCast(TypeRange inputs, TypeRange outputs) {
 static FailureOr<APFloat> convertFloatValue(
     APFloat sourceValue, const llvm::fltSemantics &targetSemantics,
     llvm::RoundingMode roundingMode = llvm::RoundingMode::NearestTiesToEven) {
+  // Reject special values that are not representable in the target type before
+  // calling APFloat::convert, which would llvm_unreachable on them.
+  using fltNonfiniteBehavior = llvm::fltNonfiniteBehavior;
+  if (sourceValue.isInfinity() &&
+      (targetSemantics.nonFiniteBehavior == fltNonfiniteBehavior::NanOnly ||
+       targetSemantics.nonFiniteBehavior == fltNonfiniteBehavior::FiniteOnly))
+    return failure();
+  if (sourceValue.isNaN() &&
+      targetSemantics.nonFiniteBehavior == fltNonfiniteBehavior::FiniteOnly)
+    return failure();
+
   bool losesInfo = false;
   auto status = sourceValue.convert(targetSemantics, roundingMode, &losesInfo);
   if (losesInfo || status != APFloat::opOK)

diff  --git a/mlir/test/Dialect/Arith/canonicalize.mlir b/mlir/test/Dialect/Arith/canonicalize.mlir
index 26b04e4209a43..643e4e076e7c6 100644
--- a/mlir/test/Dialect/Arith/canonicalize.mlir
+++ b/mlir/test/Dialect/Arith/canonicalize.mlir
@@ -3527,3 +3527,29 @@ func.func @cmpi_dynamic_shape_no_fold(%arg0: tensor<?xi32>) -> tensor<?xi1> {
   return %0 : tensor<?xi1>
 }
 
+// -----
+
+// arith.truncf of infinity to a FiniteOnly float type (f4E2M1FN) must not fold,
+// since the type has no infinity representation. Previously this would crash
+// inside APFloat::convert with llvm_unreachable("semantics don't support inf!").
+
+// CHECK-LABEL: @truncf_inf_to_finite_only_no_fold
+//       CHECK:   arith.truncf
+func.func @truncf_inf_to_finite_only_no_fold() -> f4E2M1FN {
+  %inf = arith.constant 0x7F800000 : f32
+  %result = arith.truncf %inf : f32 to f4E2M1FN
+  return %result : f4E2M1FN
+}
+
+// -----
+
+// arith.truncf of negative infinity to a FiniteOnly float type must not fold.
+
+// CHECK-LABEL: @truncf_neg_inf_to_finite_only_no_fold
+//       CHECK:   arith.truncf
+func.func @truncf_neg_inf_to_finite_only_no_fold() -> f4E2M1FN {
+  %neg_inf = arith.constant 0xFF800000 : f32
+  %result = arith.truncf %neg_inf : f32 to f4E2M1FN
+  return %result : f4E2M1FN
+}
+


        


More information about the Mlir-commits mailing list