[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:51:52 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-math

Author: tht2005

<details>
<summary>Changes</summary>

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

---
Full diff: https://github.com/llvm/llvm-project/pull/218242.diff


3 Files Affected:

- (modified) mlir/lib/Dialect/Math/Transforms/ExpandOps.cpp (+4-6) 
- (modified) mlir/test/Dialect/Math/expand-math.mlir (+6-9) 
- (modified) mlir/test/mlir-runner/test-expand-math-approx.mlir (+36) 


``````````diff
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
 }

``````````

</details>


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


More information about the Mlir-commits mailing list