llvm / llvm/llvm-project

[MLIR][Math] Miscompilation: `--math-expand-ops` loses the sign of zero when expanding `math.ceil`

Open
#218,111 2 comments 0 reactions 0 assignees View on GitHub
miscompilation mlir
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

## Reproducer

### small.mlir

```mlir
memref.global "private" @v : memref<2xf32> = dense<[-2.5e-01, -0.0]>
memref.global "private" @w : memref<2xf64> = dense<[-2.5e-01, -0.0]>

func.func @main() {
%c0 = arith.constant 0 : index
%c1 = arith.constant 1 : index

%g = memref.get_global @v : memref<2xf32>
%a = memref.load %g[%c0] : memref<2xf32>
%b = memref.load %g[%c1] : memref<2xf32>
%ca = math.ceil %a : f32
%cb = math.ceil %b : f32
vector.print %ca : f32
vector.print %cb : f32

%h = memref.get_global @w : memref<2xf64>
%d = memref.load %h[%c0] : memref<2xf64>
%e = memref.load %h[%c1] : memref<2xf64>
%cd = math.ceil %d : f64
%ce = math.ceil %e : f64
vector.print %cd : f64
vector.print %ce : f64
return
}
```

The values come out of a mutable global so that nothing folds them; with literals the program folds and the two routes agree on the folded constant.

### To reproduce

`$LLVM_LIB` is the `lib` directory of an `mlir-opt`/`mlir-runner` build; no other library is needed. The two commands differ in one pass and nothing else.

**Correct:**

```
mlir-opt small.mlir \
--convert-math-to-llvm --finalize-memref-to-llvm --convert-func-to-llvm \
--convert-arith-to-llvm --convert-vector-to-llvm --reconcile-unrealized-casts \
| mlir-runner -e main --entry-point-result=void \
--shared-libs=$LLVM_LIB/libmlir_c_runner_utils.so,$LLVM_LIB/libmlir_runner_utils.so
```

Output:
```
-0
-0
-0
-0
```

**Wrong:**
```
mlir-opt small.mlir --math-expand-ops
--convert-math-to-llvm --finalize-memref-to-llvm --convert-func-to-llvm \
--convert-arith-to-llvm --convert-vector-to-llvm --reconcile-unrealized-casts \
| mlir-runner -e main --entry-point-result=void \
--shared-libs=$LLVM_LIB/libmlir_c_runner_utils.so,$LLVM_LIB/libmlir_runner_utils.so
```

Output:
```
0
0
0
0
```

Contributor guide

Open the contributing guide

Research direction

Start by running the supplied small.mlir reproducer through mlir-opt and mlir-runner, comparing the pipelines with and without --math-expand-ops. Trace the expansion of math.ceil and add coverage for f32 and f64 negative zero. Done means the expanded path prints -0 for all four values, matching the unexpanded path.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.