[Mlir-commits] [mlir] [MLIR] Fix miscompilation when use --math-expand-ops (PR #218242)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Sun Aug 23 06:50:56 PDT 2026


https://github.com/tht2005 created https://github.com/llvm/llvm-project/pull/218242

Fix the bug in convertCeilOp that loses the sign
of zero when expanding math.ceil

>From eaace66fc1254ce3b4b1de9f3edd4b8459930249 Mon Sep 17 00:00:00 2001
From: Nguyen Dinh Dang Duong <dangduong31205 at gmail.com>
Date: Sun, 23 Aug 2026 16:45:01 +0700
Subject: [PATCH] [MLIR] Fix miscompilation when use --math-expand-ops

Fix the bug in convertCeilOp that loses the sign
of zero when expanding math.ceil
---
 .../lib/Dialect/Math/Transforms/ExpandOps.cpp | 10 +++---
 mlir/test/Dialect/Math/expand-math.mlir       | 15 ++++----
 .../mlir-runner/test-expand-math-approx.mlir  | 36 +++++++++++++++++++
 3 files changed, 46 insertions(+), 15 deletions(-)

diff --git a/mlir/lib/Dialect/Math/Transforms/ExpandOps.cpp b/mlir/lib/Dialect/Math/Transforms/ExpandOps.cpp
index 41816abf07339..98511a065e87a 100644
--- a/mlir/lib/Dialect/Math/Transforms/ExpandOps.cpp
+++ b/mlir/lib/Dialect/Math/Transforms/ExpandOps.cpp
@@ -338,16 +338,14 @@ static LogicalResult convertCeilOp(math::CeilOp op, PatternRewriter &rewriter) {
   Value fpFixedConvert = createTruncatedFPValue(operand, b);
 
   // Creating constants for later use.
-  Value zero = createFloatConst(op->getLoc(), opType, 0.00, rewriter, operand);
   Value one = createFloatConst(op->getLoc(), opType, 1.00, rewriter, operand);
 
   Value gtCheck = arith::CmpFOp::create(b, arith::CmpFPredicate::OGT, operand,
                                         fpFixedConvert);
-  Value incrValue =
-      arith::SelectOp::create(b, op->getLoc(), gtCheck, one, zero);
-
-  Value add = arith::AddFOp::create(b, opType, fpFixedConvert, incrValue);
-  Value ret = arith::SelectOp::create(b, isSpecialValOrLargeVal, operand, add);
+  Value add = arith::AddFOp::create(b, opType, fpFixedConvert, one);
+  Value rounded = arith::SelectOp::create(b, gtCheck, add, fpFixedConvert);
+  Value ret =
+      arith::SelectOp::create(b, isSpecialValOrLargeVal, operand, rounded);
   rewriter.replaceOp(op, ret);
   return success();
 }
diff --git a/mlir/test/Dialect/Math/expand-math.mlir b/mlir/test/Dialect/Math/expand-math.mlir
index 84b0bb0aa314a..5839909aa3956 100644
--- a/mlir/test/Dialect/Math/expand-math.mlir
+++ b/mlir/test/Dialect/Math/expand-math.mlir
@@ -154,7 +154,6 @@ func.func @fmaf_func(%a: f64, %b: f64, %c: f64) -> f64 {
 // CHECK-LABEL:     func @ceilf_func
 // CHECK-SAME:      ([[ARG0:%.+]]: f64) -> f64
 func.func @ceilf_func(%a: f64) -> f64 {
-  // CHECK-DAG:   [[C_0:%.+]] = arith.constant 0.000
   // CHECK-DAG:   [[C_1:%.+]] = arith.constant 1.000
   // CHECK-DAG:   [[C_4841369599423283200:%.*]] = arith.constant 4841369599423283200
   // CHECK-DAG:   [[C_9223372036854775807:%.*]] = arith.constant 9223372036854775807
@@ -165,9 +164,9 @@ func.func @ceilf_func(%a: f64) -> f64 {
   // CHECK-NEXT:   [[CVTF:%.+]] = arith.sitofp [[CVTI]]
   // CHECK-NEXT:   [[COPYSIGN:%.+]] = math.copysign [[CVTF]], [[ARG0]]
   // CHECK-NEXT:   [[COMP:%.+]] = arith.cmpf ogt, [[ARG0]], [[COPYSIGN]]
-  // CHECK-NEXT:   [[INCR:%.+]] = arith.select [[COMP]], [[C_1]], [[C_0]]
-  // CHECK-NEXT:   [[ADDF:%.+]] = arith.addf [[COPYSIGN]], [[INCR]]
-  // CHECK-NEXT:   [[RESULT:%.*]] = arith.select [[IS_SPECIAL_VAL]], [[ARG0]], [[ADDF]]
+  // CHECK-NEXT:   [[ADDF:%.+]] = arith.addf [[COPYSIGN]], [[C_1]]
+  // CHECK-NEXT:   [[ROUNDED:%.+]] = arith.select [[COMP]], [[ADDF]], [[COPYSIGN]]
+  // CHECK-NEXT:   [[RESULT:%.*]] = arith.select [[IS_SPECIAL_VAL]], [[ARG0]], [[ROUNDED]]
   // CHECK-NEXT:   return [[RESULT]]
   // CHECK-FILTER: math.ceil
   %ret = math.ceil %a : f64
@@ -179,7 +178,6 @@ func.func @ceilf_func(%a: f64) -> f64 {
 // CHECK-LABEL:     func @ceilf_fnuz_func
 // CHECK-SAME:      ([[ARG0:%.+]]: f8E5M2FNUZ) -> f8E5M2FNUZ
 func.func @ceilf_fnuz_func(%a: f8E5M2FNUZ) -> f8E5M2FNUZ {
-  // CHECK-DAG:   [[C_0:%.+]] = arith.constant 0.000
   // CHECK-DAG:   [[C_1:%.+]] = arith.constant 1.000
   // CHECK-DAG:   [[C_NEG_128:%.*]] = arith.constant -128
   // CHECK-DAG:   [[C_72:%.*]] = arith.constant 72
@@ -193,9 +191,9 @@ func.func @ceilf_fnuz_func(%a: f8E5M2FNUZ) -> f8E5M2FNUZ {
   // CHECK-NEXT:   [[CVTF:%.+]] = arith.sitofp [[CVTI]]
   // CHECK-NEXT:   [[COPYSIGN:%.+]] = math.copysign [[CVTF]], [[ARG0]]
   // CHECK-NEXT:   [[COMP:%.+]] = arith.cmpf ogt, [[ARG0]], [[COPYSIGN]]
-  // CHECK-NEXT:   [[INCR:%.+]] = arith.select [[COMP]], [[C_1]], [[C_0]]
-  // CHECK-NEXT:   [[ADDF:%.+]] = arith.addf [[COPYSIGN]], [[INCR]]
-  // CHECK-NEXT:   [[RESULT:%.*]] = arith.select [[IS_SPECIAL_VAL]], [[ARG0]], [[ADDF]]
+  // CHECK-NEXT:   [[ADDF:%.+]] = arith.addf [[COPYSIGN]], [[C_1]]
+  // CHECK-NEXT:   [[ROUNDED:%.+]] = arith.select [[COMP]], [[ADDF]], [[COPYSIGN]]
+  // CHECK-NEXT:   [[RESULT:%.*]] = arith.select [[IS_SPECIAL_VAL]], [[ARG0]], [[ROUNDED]]
   // CHECK-NEXT:   return [[RESULT]]
   // CHECK-FILTER: math.ceil
   %ret = math.ceil %a : f8E5M2FNUZ
@@ -821,7 +819,6 @@ func.func @rsqrt_tns(%float: tensor<5x8xf32>) -> (tensor<5x8xf32>)  {
 // CHECK-LABEL:    func.func @non_static_shape_ceil_op
 // CHECK-SAME:     (%[[ARG:.*]]: tensor<?xf32>)
 // CHECK-SAME:     -> tensor<?xf32>
-// CHECK-DAG:       arith.constant 0.000000e+00 : f32
 // CHECK-DAG:       arith.constant 1.000000e+00 : f32
 // CHECK-DAG:       tensor.dim %[[ARG]]
 // CHECK:           tensor.splat %{{.*}}[%{{.*}}] : tensor<?xf32>
diff --git a/mlir/test/mlir-runner/test-expand-math-approx.mlir b/mlir/test/mlir-runner/test-expand-math-approx.mlir
index 06b3171a2349e..949e5658ce58f 100644
--- a/mlir/test/mlir-runner/test-expand-math-approx.mlir
+++ b/mlir/test/mlir-runner/test-expand-math-approx.mlir
@@ -886,6 +886,41 @@ func.func @rsqrt() {
   return
 }
 
+// -------------------------------------------------------------------------- //
+// Ceil.
+// -------------------------------------------------------------------------- //
+
+func.func @ceil_f32_bits(%arg : f32) {
+  %result = math.ceil %arg : f32
+  %bits = arith.bitcast %result : f32 to i32
+  vector.print %bits : i32
+  return
+}
+
+func.func @ceil_f64_bits(%arg : f64) {
+  %result = math.ceil %arg : f64
+  %bits = arith.bitcast %result : f64 to i64
+  vector.print %bits : i64
+  return
+}
+
+func.func @ceil() {
+  %neg_fraction_f32 = arith.constant -0.25 : f32
+  %neg_zero_f32 = arith.constant 0x80000000 : f32
+  %neg_fraction_f64 = arith.constant -0.25 : f64
+  %neg_zero_f64 = arith.constant 0x8000000000000000 : f64
+
+  // CHECK: -2147483648
+  call @ceil_f32_bits(%neg_fraction_f32) : (f32) -> ()
+  // CHECK-NEXT: -2147483648
+  call @ceil_f32_bits(%neg_zero_f32) : (f32) -> ()
+  // CHECK-NEXT: -9223372036854775808
+  call @ceil_f64_bits(%neg_fraction_f64) : (f64) -> ()
+  // CHECK-NEXT: -9223372036854775808
+  call @ceil_f64_bits(%neg_zero_f64) : (f64) -> ()
+  return
+}
+
 func.func @main() {
   call @exp2f() : () -> ()
   call @roundf() : () -> ()
@@ -898,5 +933,6 @@ func.func @main() {
   call @acosh() : () -> ()
   call @atanh() : () -> ()
   call @rsqrt() : () -> ()
+  call @ceil() : () -> ()
   return
 }



More information about the Mlir-commits mailing list